home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1993 / MacHack 1993.toast / MacHack™ 1987-1992 / MacHack™ '90 / Other Stuff / Demos ƒ / Word Solution Engine DEMO / Raw Text Files / WSDemo.p < prev   
Encoding:
Text File  |  1990-06-14  |  57.9 KB  |  2,800 lines  |  [TEXT/MPS ]

  1.           {$M-}
  2.           {$R-}
  3.  
  4.  
  5.           
  6.           PROGRAM   WSTEST;
  7.  
  8.  
  9.  
  10.      USES   MemTypes, QuickDraw, OsIntf, ToolIntf, PackIntf,MacPrint,
  11.              PickerIntf,Script,WSIntf;
  12.  
  13. {$S  }
  14.  
  15.  
  16.     {  THE MENU VARIABLES:
  17.  
  18.           MENU0         Apple menu     ID 1
  19.           MENU1         File            ID 100
  20.           MENU2         Edit            ID 200
  21.           MENU3         Font            ID 300
  22.           MENU4         Style            ID 400
  23.           MENU5         Point            ID 500
  24.           MENU6         Format            ID 600
  25.           MENU7         Demo            ID 700  }
  26.  
  27.  
  28. {  ALERT & DIALOG ID'S  }
  29.  
  30.     CONST    AboutAlert = 128;        { About Screen }
  31.             MemFailed = 129;        { Memory error }
  32.             SaveChanges = 130;        { Save changes yes/no }
  33.             CantUndo = 131;            { Cannot create UNDO buffer }
  34.             PtSizeDLG = 132;        { Custom point size }
  35.             WrapDLG    =    134;        { Word-wrap characteristics }
  36.             AddOnAlert = 136;        { About the add-ons }
  37.             AskScrap = 140;            { Ask if clipboard should be saved }
  38.             StupidTester = 142;        { Some fool is trying to crash program }
  39.             BadFonts = 144;            { Some wrong fonts kicking around }
  40.             OpenDLG = 4000;            { OPEN dialog }
  41.             ExportDLG = 3000;        { EXPORT text dialog }
  42.             
  43.     
  44. TYPE MyWS = RECORD
  45.        WS:WSHandle;                { Handle for this screen }
  46.        vRef:Integer;            { Volume reference }
  47.        fRef:Integer;            { File ref }
  48.        Undo:Integer;            { Last action (used for UNDO) }
  49.        UnSel1:LongInt;            { Undo selection 1 }
  50.        UnSel2:LongInt;            { Undo selection 2 }
  51.        UnSel3:LongInt;            { Last mouse-click }
  52.        vCTL:ControlHandle;        { Vertical scroll }
  53.        hCTL:ControlHandle;        { Horizontal scroll }
  54.        vOffset:LongInt;            { Vertical offset }
  55.        hOffset:LongInt;            { Horizontal offset }
  56.        Change:Boolean;            { Changes yes/no }
  57.      END;
  58.  
  59.      MyWSPtr = ^MyWS;            { Pointer to the above }
  60.      IntWidths = ARRAY[0..0] OF INTEGER;
  61.      WidTablePtr = ^IntWidths;
  62.     
  63. VAR WS,UndoWS,ScrapWS:WSHandle;
  64.     FontScrap:FormatHandle;
  65.     CurWS:MyWS;
  66.     R1:Rect;
  67.     LocalMouse:Point;
  68.     MyBounds:LongRect;
  69.     MainWindow,ClipWindow:WindowPtr;
  70.     EV:EventRecord;
  71.     X,CurCursor,ShowCtr,io,MyScrapNum,OpenSelect,ExpSel,AppMsg,nFiles:Integer;
  72.     AppData:AppFile;
  73.     Quit,OpFailed,CXL,MyOwnScrap:Boolean;
  74.     Menu0,Menu1,Menu2,Menu3,Menu4,Menu5,Menu6,Menu7:MenuHandle;
  75.     LastNumChars:LongInt;
  76.     AppleChar,MastSTR:STR255;
  77.     xScrap:pScrapStuff;
  78.     DefFlags:LongInt;
  79.  
  80.     PHDL:THPrint;
  81.     PStatus:TPRStatus;
  82.     PrintPort:TPPrPort;
  83.  
  84.  
  85. PROCEDURE Bomb;
  86. INLINE $A9FF;
  87.  
  88.  
  89. PROCEDURE GetXScrap;
  90. VAR TheView:Rect;
  91.     MyBounds:LongRect;
  92.     
  93. BEGIN
  94.    XScrap:= InfoScrap;
  95.    IF XScrap^.scrapCount <> MyScrapNum
  96.    THEN
  97.    BEGIN
  98.        SetRect(TheView,0,0,512,320);        { Some arbitrary number }
  99.        MyBounds.Left:= 0;
  100.        MyBounds.Top:= 0;
  101.        MyBounds.Right:= 512;
  102.        MyBounds.Bottom:= 320;
  103.        IF ScrapWS <> NIL THEN WSDispose(ScrapWS);
  104.        ScrapWS:= WSScrapToHandle(TheView,MyBounds,0,NIL,NIL);
  105.    END;
  106.    MyScrapNum:= XScrap^.scrapCount;
  107. END;
  108.  
  109.  
  110. PROCEDURE PutXScrap;
  111. BEGIN
  112.    IF ScrapWS = NIL THEN EXIT(PutXScrap);
  113.    WSToScrap(ScrapWS);
  114.    XScrap:= InfoScrap;
  115.    MyScrapNum:= XScrap^.scrapCount;
  116. END;
  117.  
  118.  
  119. PROCEDURE SetMouse (C:Integer);
  120. VAR CC:CursHandle;
  121.     CCC:Cursor;
  122.     
  123. BEGIN
  124.    IF C = CurCursor THEN EXIT(SetMouse);
  125.    CurCursor:= C;
  126.    IF CurCursor = 0 THEN InitCursor
  127.    ELSE
  128.    BEGIN
  129.       CC:= GetCursor(C);
  130.       CCC:= CC^^;
  131.       SetCursor(CCC);
  132.    END;
  133. END;
  134.  
  135.  
  136. FUNCTION What4Scrap:Boolean;
  137. BEGIN
  138.    What4Scrap:= TRUE;
  139.    IF NOT MyOwnScrap THEN EXIT(What4Scrap);
  140.  
  141.    IF ScrapWS = NIL THEN EXIT (What4Scrap);
  142.    IF ScrapWS^^.tLength < 100 THEN EXIT(What4Scrap);
  143.       
  144.    SetMouse(0);
  145.    io:= CautionAlert(AskScrap,NIL);
  146.    CASE io OF
  147.       
  148.       1: PutXScrap;
  149.       2: What4Scrap:= FALSE;
  150.    END;
  151. END;
  152.  
  153.  
  154.  
  155. PROCEDURE ShowNumChars;                { Shows # of chars per current window }
  156. VAR R:Rect;
  157.     Work1,Work2:LongInt;
  158.     i,n:Integer;
  159.     NumStr:STR255;
  160.     
  161.       PROCEDURE BCD(Power:LongInt);
  162.       BEGIN
  163.          n:= 48;                { Start with zero }
  164.          REPEAT
  165.             Work1:= Work1-Power;
  166.             n:= n+1;
  167.          UNTIL Work1 < 0;
  168.          Work1:= Work1+Power;
  169.          n:= n-1;
  170.          
  171.          IF n <> 48 THEN
  172.          BEGIN
  173.             NumStr[i]:= CHR(n);
  174.             i:= i+1;
  175.          END
  176.          ELSE
  177.          IF i > 1
  178.          THEN
  179.          BEGIN
  180.             NumStr[i]:= CHR(n);
  181.             i:= i+1;
  182.          END;
  183.       END;
  184.       
  185. BEGIN
  186.     IF WS^^.tLength-2 = LastNumChars THEN EXIT(ShowNumChars);
  187.     
  188.     LastNumChars:= WS^^.tLength-2;
  189.     SetPort(MainWindow);
  190.     TextFont(0);
  191.     TextSize(12);
  192.     TextFace([]);
  193.     
  194.     R:= CurWS.hCTL^^.contrlRect;
  195.     R.Right:= 120;
  196.     R.Left:= 0;
  197.     EraseRect(R);
  198.     PenSize(1,1);
  199.     PenPat(Black);
  200.     PenMode(PatCopy);
  201.     FrameRect(R);
  202.     
  203.     Work1:= LastNumChars;
  204.     NumStr:= '9999999';
  205.     i:= 1;
  206.     BCD(1000000);
  207.     BCD(100000);
  208.     BCD(10000);
  209.     BCD(1000);
  210.     BCD(100);
  211.     BCD(10);
  212.     NumStr[i]:= CHR(Work1+48);
  213.     NumStr[0]:= CHR(i);
  214.     
  215.     MOVETO(R.left+4,R.Bottom-3);
  216.     DrawString(NumStr);
  217.     DrawString(' Chars');
  218. END;
  219.  
  220. PROCEDURE CaretOff;
  221. BEGIN
  222.    IF MainWindow = NIL THEN EXIT(CaretOff);
  223.    SetPort(MainWindow);
  224.    WSSetCaret(WS,FALSE);
  225. END;
  226.  
  227.  
  228. PROCEDURE GetMyWS (W:WindowPtr);  { Sets CurWS and MainWindow }
  229. VAR TempWS:MyWSPtr;
  230.  
  231. BEGIN
  232.    MainWindow:= W;
  233.    IF MainWindow = NIL THEN Exit(GetMyWS);
  234.  
  235.    TempWS:= MyWSPtr(GetWRefCon(W));
  236.    IF TempWS = NIL THEN MainWindow:= NIL
  237.    ELSE
  238.    BEGIN
  239.       WS:= TempWS^.WS;
  240.       BlockMove(Ptr(TempWS),Ptr(@CurWS),SizeOf(CurWS));
  241.    END;
  242. END;
  243.  
  244.  
  245. PROCEDURE SetMyWS (W:WindowPtr);  { Puts CurWS into Window }
  246. VAR TempWS:MyWSPtr;
  247.  
  248. BEGIN
  249.    TempWS:= MyWSPtr(GetWRefCon(W));
  250.    BlockMove(Ptr(@CurWS),Ptr(TempWS),SizeOf(CurWS));
  251. END;
  252.  
  253. PROCEDURE SetChanges(C:Boolean);
  254. BEGIN
  255.    CurWS.Change:= C;
  256.    SetMyWS(MainWindow);
  257. END;
  258.  
  259.  
  260. PROCEDURE InvalScrap;
  261. BEGIN
  262.    IF ClipWindow = NIL THEN EXIT(InvalScrap);
  263.    SetPort(ClipWindow);
  264.    InvalRect(ClipWindow^.PortRect);
  265. END;
  266.  
  267. PROCEDURE ForceUpdate;
  268. FORWARD;
  269.  
  270.  
  271.  PROCEDURE ReHabPrint;        { Forces Print Driver to behave itelf }
  272.  VAR Dummy:Boolean;
  273.  BEGIN
  274.     PrClose;
  275.     PrOpen;
  276.     Dummy:= PrValidate(PHDL);
  277.  END;
  278.  
  279.  
  280.   FUNCTION Str2Num(nSTR:STR255):Integer;
  281.   VAR Value,X,Y,rRound:Integer;
  282.       iSTR:STR255;
  283.  
  284.   BEGIN
  285.      Value:= 0;            { Assume nothing }
  286.  
  287.      iSTR:= nSTR;
  288.  
  289.      IF Length(iSTR) > 0 THEN
  290.      BEGIN
  291.         IF iSTR[1] = '-'  { IF NEGATIVE }
  292.         THEN iSTR[1]:= '0';
  293.  
  294.         FOR Y:= 1 TO Length(iSTR) DO
  295.         BEGIN
  296.            X:= ORD(iSTR[Y])-48;          { ASCII-ness = decimal }
  297.  
  298.            IF (X >= 0) AND (X < 10)
  299.            THEN Value:= Value*10+X;
  300.         END;
  301.      END;
  302.  
  303.      IF nSTR[1] = '-' { If original was MINUS }
  304.      THEN
  305.      BEGIN
  306.         X:= 0;
  307.         Value:= X-Value;      { Negate }
  308.      END;
  309.  
  310.      Str2Num:= Value;
  311.   END;
  312.  
  313.  
  314.  { Reverse of the above }
  315.  
  316.  PROCEDURE Num2Str(Num:Integer; VAR S:STR255);
  317.  VAR ZeroFlag:Boolean;
  318.      X,Y,Value:Integer;
  319.  
  320.      PROCEDURE ASCIIChar(SubVal:Integer);
  321.      VAR D:Integer;
  322.  
  323.      BEGIN
  324.         D:= 48;         { ASCII ZERO }
  325.         REPEAT
  326.            Value:= Value-SubVal;
  327.            D:= D+1;
  328.         UNTIL Value < 0;
  329.         Value:= Value+SubVal;
  330.         D:= D-1;
  331.         IF D > 48 THEN ZeroFlag:= FALSE;  { Do not suppress zeros }
  332.  
  333.         IF NOT ZeroFlag THEN
  334.         BEGIN
  335.            S[Y]:= CHR(D);       { Add a char }
  336.            Y:= Y+1;
  337.         END;
  338.      END;
  339.  
  340.  BEGIN
  341.  
  342.     S:= '      ';     { Init string }
  343.     ZeroFlag:= TRUE;     { Suppress zeros }
  344.     Y:= 1;         { Index into output string }
  345.  
  346.     Value:= NUM;
  347.  
  348.     IF Num < 0  { If negative number } THEN
  349.     BEGIN
  350.        S[1]:= '-';     { Minus sign }
  351.        Y:= 2;         { Index 2nd char }
  352.        Value:= 0;
  353.        Value:= Value-Num;  { Reverse polarity }
  354.     END;
  355.  
  356.     ASCIICHAR(10000);
  357.     ASCIICHAR(1000);
  358.     ASCIICHAR(100);
  359.     ASCIICHAR(10);
  360.  
  361.     S[Y]:= CHR(Value+48);       { = last digit }
  362.  
  363.     S[0]:= CHR(Y);           { .. and set string length }
  364.  END;
  365.  
  366.  
  367.  
  368. FUNCTION NumProc(TheDLG:DialogPtr; VAR EV:EventRecord;
  369.                     VAR ItemAction:Integer):Boolean;
  370.  
  371. VAR X,DummyType:Integer;
  372.     DummyRect:RECT;
  373.     ItemHDL:Handle;
  374.     K:Packed Array[0..1] OF CHAR;
  375.  
  376. BEGIN
  377.    NumProc:= FALSE;          { I need no special handling }
  378.  
  379.    IF (EV.What = 8) AND (BitAND(EV.Modifiers,1) = 1) { If ACTIVATE }
  380.    THEN
  381.    BEGIN
  382.       { Time to set up default Pic Props }
  383.  
  384.       GetDItem(TheDLG,3,DummyType,ItemHDL,DummyRect);
  385.       SetIText(ItemHDL,MastSTR);
  386.       SelIText(TheDLG,3,0,Length(MastSTR));    { .. and select text }
  387.    END
  388.    ELSE
  389.    IF (EV.What = 3) OR (EV.What = 5)  { IF KEYSTROKE }
  390.    THEN
  391.    BEGIN
  392.       X:= LoWord(EV.Message);
  393.       K[0]:= CHR(X);
  394.       IF K[0] = CHR(13)     { IF CR }
  395.       THEN
  396.       BEGIN
  397.          ItemAction:= 1;
  398.          NumProc:= TRUE;
  399.       END;
  400.    END;
  401. END;
  402.  
  403.  
  404.  
  405.  { The following function returns a numeric value entered by user }
  406.  
  407.   FUNCTION NumDialog(DlgID:Integer; VAR Value:Integer):Boolean;
  408.  
  409.  
  410.   VAR MakePtr:DialogPtr;
  411.       EndAction,ACCEPT:Boolean;
  412.       ItemAction,iType,X,Y:Integer;
  413.       ItemHDL:Handle;
  414.       iRect:RECT;
  415.       iSTR:STR255;
  416.  
  417.   BEGIN
  418.      Num2STR(Value,MastSTR);
  419.      CaretOff;
  420.      
  421.      MakePtr:= GetNewDialog(DlgID,NIL,Pointer(-1));
  422.  
  423.      EndAction:= FALSE;      { Flag TRUE when done }
  424.      ACCEPT:= TRUE;      { Assume accepted }
  425.  
  426.      REPEAT
  427.  
  428.         ModalDialog(@NumProc,ItemAction);
  429.  
  430.         CASE ItemAction OF
  431.  
  432.            1: { OK }
  433.               EndAction:= TRUE;
  434.  
  435.            2: { CANCEL }
  436.               BEGIN
  437.                  EndAction:= TRUE;
  438.                  ACCEPT:= FALSE;
  439.               END;
  440.         END; { of CASE }
  441.  
  442.      UNTIL EndAction;
  443.  
  444.      IF ACCEPT { If User clicked "OK" } THEN
  445.      BEGIN
  446.         GetDItem(MakePtr,3,iType,ItemHDL,iRect);   { Get TEXT ITEM }
  447.         GetIText(ItemHDL,iSTR);
  448.  
  449.         Value:= Str2Num(iSTR);       { Translate string to number }
  450.  
  451.      END;
  452.  
  453.      DisposDialog(MakePtr);
  454.      NumDialog:= ACCEPT;   { Returns CANCEL or not }
  455.   END;
  456.  
  457.  
  458.  
  459.  
  460.  
  461. FUNCTION WrapProc(TheDLG:DialogPtr; VAR EV:EventRecord;
  462.                     VAR ItemAction:Integer):Boolean;
  463.  
  464. VAR X,DummyType:Integer;
  465.     DummyRect:RECT;
  466.     ItemHDL1,ItemHDL2:Handle;
  467.     K:Packed Array[0..1] OF CHAR;
  468.  
  469. BEGIN
  470.    WrapProc:= FALSE;          { I need no special handling }
  471.  
  472.    IF (EV.What = 8) AND (BitAND(EV.Modifiers,1) = 1) { If ACTIVATE }
  473.    THEN
  474.    BEGIN
  475.       GetDItem(TheDLG,3,DummyType,ItemHDL1,DummyRect);
  476.       GetDItem(TheDLG,4,DummyType,ItemHDL2,DummyRect);
  477.       SetCTLValue(ControlHandle(ItemHDL1),0);
  478.       SetCTLValue(ControlHandle(ItemHDL2),0);
  479.  
  480.       IF DefFlags = NoWrap THEN SetCTLValue(ControlHandle(ItemHDL2),1)
  481.       ELSE SetCTLValue(ControlHandle(ItemHDL1),1);
  482.    END
  483.    ELSE
  484.    IF (EV.What = 3) OR (EV.What = 5)  { IF KEYSTROKE }
  485.    THEN
  486.    BEGIN
  487.       X:= LoWord(EV.Message);
  488.       K[0]:= CHR(X);
  489.       IF K[0] = CHR(13)     { IF CR }
  490.       THEN
  491.       BEGIN
  492.          ItemAction:= 1;
  493.          WrapProc:= TRUE;
  494.       END;
  495.    END;
  496. END;
  497.  
  498.  
  499.  { The following function returns the type of word-wrapping to do }
  500.  
  501.  FUNCTION GetWrapType:Boolean;
  502.  
  503.   VAR MakePtr:DialogPtr;
  504.       EndAction,ACCEPT:Boolean;
  505.       ItemAction,iType:Integer;
  506.       ItemHDL:Handle;
  507.       iRect:RECT;
  508.  
  509.   BEGIN
  510.      MakePtr:= GetNewDialog(134,NIL,Pointer(-1));
  511.  
  512.      EndAction:= FALSE;      { Flag TRUE when done }
  513.      ACCEPT:= TRUE;      { Assume accepted }
  514.      SetMouse(0);
  515.  
  516.      REPEAT
  517.  
  518.         ModalDialog(@WrapProc,ItemAction);
  519.  
  520.         CASE ItemAction OF
  521.  
  522.            1: { OK }
  523.               EndAction:= TRUE;
  524.  
  525.            2: { CANCEL }
  526.               BEGIN
  527.                  EndAction:= TRUE;
  528.                  ACCEPT:= FALSE;
  529.               END;
  530.            
  531.            3: BEGIN
  532.                  GetDItem(MakePtr,3,iType,ItemHDL,iRect);
  533.                  SetCTLValue(ControlHandle(ItemHDL),1);
  534.                  GetDItem(MakePtr,4,iType,ItemHDL,iRect);
  535.                  SetCTLValue(ControlHandle(ItemHDL),0);
  536.               END;
  537.            
  538.            4: BEGIN
  539.                  GetDItem(MakePtr,3,iType,ItemHDL,iRect);
  540.                  SetCTLValue(ControlHandle(ItemHDL),0);
  541.                  GetDItem(MakePtr,4,iType,ItemHDL,iRect);
  542.                  SetCTLValue(ControlHandle(ItemHDL),1);
  543.               END;
  544.               
  545.            
  546.         END; { of CASE }
  547.  
  548.      UNTIL EndAction;
  549.  
  550.      IF ACCEPT { If User clicked "OK" } THEN
  551.      BEGIN
  552.         GetDItem(MakePtr,3,iType,ItemHDL,iRect);   { Get TEXT ITEM }
  553.         IF GetCTLValue(ControlHandle(ItemHDL)) = 1
  554.         THEN DefFlags:= 0
  555.         ELSE DefFlags:= NoWrap;
  556.      END;
  557.  
  558.      DisposDialog(MakePtr);
  559.      GetWrapType:= ACCEPT;   { Returns CANCEL or not }
  560.   END;
  561.  
  562.  
  563.  
  564. PROCEDURE SetFontUndo;
  565. BEGIN
  566.     WSGetSelect(WS,CurWS.unSel1,CurWS.unSel2);
  567.     IF FontScrap <> NIL THEN DisposHandle(Handle(FontScrap));
  568.  
  569.     FontScrap:= WSCopyFormat(WS);
  570.     CurWS.Undo:= 1;                { Format change }
  571. END;
  572.  
  573.  
  574. PROCEDURE ShowClipBoard;
  575. BEGIN
  576.    IF (ClipWindow <> NIL) AND (ClipWindow = FrontWindow)
  577.    THEN
  578.    BEGIN
  579.       DisposeWindow(ClipWindow);
  580.       ClipWindow:= NIL;
  581.    END
  582.    ELSE 
  583.    BEGIN
  584.        IF ClipWindow = NIL
  585.        THEN ClipWindow:= GetNewWindow(257,NIL,Pointer(-1))
  586.        ELSE SelectWindow(ClipWindow);
  587.           InvalScrap;    { Cause clipboard to draw }
  588.    END;
  589. END;
  590.  
  591.  
  592.  
  593. { GetMaxScroll -- returns maximum scroll values for h/v }
  594. PROCEDURE GetMaxScroll (VAR hMax,vMax:LongInt);
  595. VAR Work1,Work2:LongInt;
  596.     TheBounds:LongRect;
  597.     
  598. BEGIN
  599.     WSGetScrollState(WS,CurWS.hOffset,CurWS.vOffset);
  600.  
  601.     WSGetBounds(WS,TheBounds);                    { So I know how far text goes }
  602.     Work1:= TheBounds.Bottom-TheBounds.Top;        { Height of bounds }
  603.     Work2:= WS^^.tRect.Top;                    { Top edge of view }
  604.     Work1:= Work1+Work2;                    { Bounds if it never scrolled }
  605.     Work2:= WS^^.tRect.Bottom;                { Bottom of vis edge }
  606.     
  607.     vMax:= Work1-Work2+32;                    { = maximum v-scroll }
  608.     IF vMax < 0 THEN vMax:= 0;                { Can't have negative MAX }
  609.  
  610.     Work1:= TheBounds.Right-TheBounds.Left;        { Width of bounds }
  611.     Work2:= WS^^.tRect.Left;                    { Left edge of view }
  612.     Work1:= Work1+Work2;                    { Bounds if it never scrolled }
  613.     Work2:= WS^^.tRect.Right;                { Right of vis edge }
  614.     
  615.     hMax:= Work1-Work2;                        { = maximum v-scroll }
  616.     IF hMax < 0 THEN hMax:= 0;                { Can't have negative MAX }
  617.     
  618. END;
  619.  
  620.  
  621. PROCEDURE MakeNewControls(W:WindowPtr);
  622. VAR R1,R2:Rect;
  623. BEGIN
  624.    R1:= W^.PortRect;
  625.    R2:= R1;
  626.    R1.Left:= R1.Right-16;
  627.    R1.Bottom:= R1.Bottom-13;
  628.    OffsetRect(R1,1,-1);
  629.    
  630.    R2.Top:= R2.Bottom-16;
  631.    R2.Right:= R2.Right-13;
  632.    OffsetRect(R2,-1,1);
  633.    
  634.    R2.Left:= R2.Left+120;                { So I can show "chars.." }
  635.    
  636.    CurWS.vCTL:= NewControl(W,R1,' ',FALSE,0,0,720,16,0);
  637.    CurWS.hCTL:= NewControl(W,R2,' ',FALSE,0,0,64,16,0);
  638.    
  639. END;
  640.  
  641.  
  642. PROCEDURE SetMaxScroll;  { Sets the two scroll bars to maximum scroll values }
  643. VAR hMax,vMax,SH,SV:LongInt;
  644.     h,V,OldH,OldV,X:Integer;
  645. BEGIN
  646.     GetMaxScroll(hMax,vMax);            { Obtain max pixels }
  647.     OldH:= GetCTLMax(CurWS.hCTL);
  648.     OldV:= GetCTLMax(CurWS.vCTL);
  649.     
  650.     H:= hMax DIV 8;
  651.     V:= vMax DIV 8;
  652.     SetCTLMax(CurWS.vCTL,V);
  653.     SetCTLMax(CurWS.hCTL,H);
  654.     
  655.     IF (OldH <> H) OR (OldV <> V)
  656.     THEN
  657.     BEGIN
  658.         X:= CurWS.VOffset DIV 8;
  659.         SetCTLValue(CurWS.vCTL,X);
  660.         
  661.         X:= CurWS.hOffset DIV 8;
  662.         SetCTLValue(CurWS.hCTL,X);
  663.     END;
  664.     
  665.     IF OldH <> H
  666.     THEN
  667.     BEGIN
  668.        IF (H = 0) AND (OldH <> 0) THEN HiliteControl(CurWS.hCTL,255)
  669.        ELSE
  670.        IF (OldH = 0) AND (H <> 0) THEN HiliteControl(CurWS.hCTL,0);
  671.     END;
  672.     
  673.     IF OldV <> V
  674.     THEN
  675.     BEGIN
  676.        IF (V = 0) AND (OldV <> 0) THEN HiliteControl(CurWS.vCTL,255)
  677.        ELSE
  678.        IF (OldV = 0) AND (V <> 0) THEN HiliteControl(CurWS.vCTL,0);
  679.     END;
  680.     
  681.     IF (H = 0) OR (V = 0) THEN
  682.     BEGIN
  683.        WSGetScrollState(WS,SH,SV);
  684.        IF H <> 0 THEN SH:= 0;        { Unaffected }
  685.        IF V <> 0 THEN SV:= 0;        { Unaffected }
  686.        
  687.        IF (SH <> 0) OR (SV <> 0) THEN WSScroll(WS,SH,SV);
  688.      { THE ABOVE FIXES A PROBLEM WHERE SCREEN IS PARTIALLY SCROLLED YET
  689.          SCROLL BARS ARE DISABLED ! }
  690.     END;
  691. END;
  692.  
  693. PROCEDURE ForceScroll;
  694. FORWARD;
  695.  
  696. PROCEDURE ReDisplay;                { Called when WS needs updating }
  697. BEGIN
  698.    WSBitMapDisplay(WS,0,SrcCopy,TRUE);
  699.    ForceScroll;
  700.    SetMaxScroll;
  701. END;
  702.  
  703.  
  704.  { MasterScroll -- scrolls h/v pixels. It also fixes H,V amounts so they
  705.   do not scroll the window too far up or down. Since H & V are VAR params,
  706.   those who call this now have the actual scrolled amounts }
  707.  
  708.  PROCEDURE MasterScroll (VAR h,v:LongInt);
  709.  VAR hMax,vMax,OldVMax,OldHMax,hMove,vMove:LongInt;
  710.      X:Integer;
  711.      
  712.      PROCEDURE FixScroll (VAR Value:LongInt; Base,Max:LongInt);
  713.      VAR Work:LongInt;
  714.      BEGIN
  715.         Work:= Base-Value;    { Where it WILL wind up }
  716.         IF Work < 0 THEN Value:= Base  { Can only subtract what's left }
  717.         ELSE
  718.         IF Work > Max  { If gone too far }
  719.         THEN Value:= Base-Max;   { Scroll negative diff between current & Max }
  720.      END;
  721.  
  722.  BEGIN    
  723.     GetMaxScroll(hMax,vMax);
  724.     OldHMax:= hMax;
  725.     OldVMax:= vMax;                    { Save in case it changed on fly }
  726.  
  727.     FixScroll(h,CurWS.hOffset,hMax);
  728.     FixScroll(v,CurWS.vOffset,vMax);
  729.     
  730.     IF (H = 0) AND (V = 0) THEN EXIT(MasterScroll);   { Nothing to do! }
  731.  
  732. { Record the current position of tBounds }
  733.  
  734.     hMove:= WS^^.tBounds.Left;
  735.     vMove:= WS^^.tBounds.Top;
  736.  
  737.     WSScroll(WS,h,v);
  738.  
  739.     ClipRect(MainWindow^.PortRect);
  740.  
  741.     GetMaxScroll(hMax,vMax);
  742.     IF (hMax <> OldHMax) OR (vMax <> OldVMax)
  743.     THEN SetMaxScroll;                        { It changed during display! }
  744.     
  745.     WSGetScrollState(WS,CurWS.hOffset,CurWS.vOffset);
  746.     
  747.     X:= CurWS.VOffset DIV 8;
  748.     SetCTLValue(CurWS.vCTL,X);
  749.     
  750.     X:= CurWS.hOffset DIV 8;
  751.     SetCTLValue(CurWS.hCTL,X);
  752.     
  753.     SetMyWS(MainWindow);
  754.         
  755.  END;
  756.  
  757.  
  758. PROCEDURE ForceScroll;        { Determines whether or not to scroll to caret }
  759. VAR L:LongRect;
  760.     e,b,v,h:LongInt;
  761.     Pix:Integer;
  762. BEGIN
  763.    WSGetSelect(WS,e,b);
  764.    IF e <> b THEN EXIT(ForceScroll);        { Never if selection }
  765.    
  766.    WSLine2Rect(WS,L,Pix);                    { See where line is }
  767.    v:= 0;                                    { Assume no v-scroll }
  768.    h:= 0;                                    { Assume no H-scroll }
  769.    
  770.    e:= WS^^.tRect.Top;
  771.    b:= WS^^.tRect.Bottom;                    { Converts to longints }
  772.    
  773.    IF L.Top < e      { If line's top above view }
  774.    THEN v:= e-L.Top+16        { Then scroll this much }
  775.    ELSE
  776.    IF L.Bottom > b  { If line's bottom is below view }
  777.    THEN v:= b-L.Bottom-16;    { Then scroll this much }
  778.   
  779. { See if H-SCROLL }
  780.  
  781.    e:= Pix;                                    { Convert to longint }
  782.    L.Left:= L.Left+e;                        { Where the edge is }
  783.    e:= WS^^.tRect.Left;
  784.    b:= WS^^.tRect.Right;
  785.  
  786.    IF L.Left < e      { If line's left of view }
  787.    THEN h:= e-L.Left+16        { Then scroll this much }
  788.    ELSE
  789.    IF L.Left > b         { If line's right of view }
  790.    THEN h:= b-L.Left-16;    { Then scroll this much }
  791.  
  792.    IF (V <> 0) OR (H <> 0)  { If I have something }
  793.    THEN
  794.    BEGIN
  795.       SetMaxScroll;
  796.       MasterScroll(H,V);
  797.    END;
  798. END;
  799.  
  800.  
  801. PROCEDURE DoImport;  { IMPORT A TEXT FILE }
  802. VAR FileReply:SFReply;
  803.      FTypes:SFTypeList;
  804.      P:Point;
  805.      FileName:STR255;
  806.      Error,fVol,fRef:Integer;
  807.      CH:Handle;
  808.      fSize,S1,S2:LongInt;
  809.      WSP:WSHandle;
  810.      MyView:Rect;
  811.      MyBounds:LongRect;
  812.      CurFormat:FormatRec;
  813.      
  814. BEGIN
  815.      P.H:= 100;
  816.      P.V:= 80;
  817.      FTypes[0]:= 'TEXT';
  818.      
  819.      CaretOff;
  820.      
  821.      SFGetFile(P,' ',NIL,1,FTypes,NIL,FileReply);
  822.      
  823.      IF NOT FileReply.Good THEN EXIT(DoImport);
  824.      SetMouse(4);
  825.      ForceUpdate;
  826.      GetMyWS(FrontWindow);
  827.      SetPort(MainWindow);
  828.      
  829.      FileName:= FileReply.fName;
  830.      fVol:= FileReply.vRefNum;
  831.  
  832.      Error:= FSOpen(FileName,fVol,fRef);
  833.  
  834.      Error:= GetEOF(fRef,fSize);         { Get logical file size }
  835.  
  836.      CH:= NewHandle(fSize);
  837.      
  838.      IF OpFailed THEN EXIT(DoImport);
  839.      
  840.      HLOCK(CH);
  841.  
  842.      Error:= FSRead(fRef,fSize,Pointer(@CH^^));
  843.      HUNLOCK(CH);
  844.  
  845.      Error:= FSClose(fRef);
  846.  
  847.      SetRect(MyView,0,0,512,300);        { Set to any old thing }
  848.      MyBounds.Left:= 0;
  849.      MyBounds.Top:= 0;
  850.      MyBounds.Right:= 680;
  851.      MyBounds.Bottom:= 300;
  852.      
  853.      CurFormat:= WS^^.tFmt;                { Get current format of WS }
  854.      WSP:= WSText2New (CH,MyView,MyBounds,0,NIL,@CurFormat);
  855.      DisposHandle(CH);
  856.      
  857.      IF OpFailed THEN EXIT(DoImport);
  858.      
  859.      WSGetSelect(WS,S1,S2);
  860.      
  861.      IF WSPaste(WSP,WS) THEN ReDisplay;
  862.      
  863.      WSGetSelect(WS,fSize,S2);    { So I can do UNDO }
  864.      CurWS.Undo:= 2;
  865.      CurWS.unSel1:= S1;
  866.      CurWS.unSel2:= S2;
  867.      CurWS.Change:= TRUE;
  868.      SetMyWS(MainWindow);
  869.      WSDispose(WSP);
  870.  END;
  871.  
  872.  
  873. { EXPORTING TEXT }
  874.  
  875. { This is the DialogProc for EXPORT }
  876.  
  877. FUNCTION ExpGet(Item:Integer; theDialog:DialogPtr):Integer;
  878. VAR CT1,CT2:Handle;
  879.     T,X,Val:Integer;
  880.     R:RECT;
  881.  
  882. BEGIN
  883.    ExpGet:= ITEM;
  884.  
  885.    IF ITEM = -1 THEN  { TIME TO INITIALIZE! }
  886.    BEGIN
  887.       FOR X:= 9 TO 10 DO
  888.       BEGIN
  889.          GetDItem(theDialog,9,T,CT1,R);
  890.          IF ExpSel = 1 THEN Val:= 1
  891.          ELSE Val:= 0;
  892.          SetCTLValue(ControlHandle(CT1),Val);
  893.          
  894.          IF ExpSel = 3  { IF IMPOSSIBLE TO SELECT }
  895.          THEN HiliteControl(ControlHandle(CT1),255);
  896.  
  897.          GetDItem(theDialog,10,T,CT1,R);
  898.          IF ExpSel <> 1 THEN Val:= 1
  899.          ELSE Val:= 0;
  900.          SetCTLValue(ControlHandle(CT1),Val);
  901.       END;
  902.    END
  903.    ELSE
  904.    BEGIN
  905.       IF (Item = 9) OR (Item = 10) THEN
  906.       BEGIN
  907.          FOR X:= 9 TO 10 DO
  908.          BEGIN
  909.             GetDItem(theDialog,X,T,CT1,R);
  910.             IF X = Item THEN Val:= 1 ELSE Val:= 0;
  911.             SetCTLValue(ControlHandle(CT1),Val);  { Set if THIS FILE  }
  912.          END;
  913.          
  914.          ExpSel:= Item;
  915.       END
  916.    END;
  917. END;
  918.  
  919.  
  920.  
  921. Procedure DoExport;
  922.  
  923. VAR FileReply:SFReply;
  924.      FTypes:SFTypeList;
  925.      P:Point;
  926.      FileName:STR255;
  927.      Error,fVol,fRef:Integer;
  928.      CH:Handle;
  929.      fSize,S1,S2:LongInt;
  930.      
  931.  BEGIN
  932.     CaretOff;
  933.     
  934.     WSGetSelect(WS,S1,S2);
  935.     
  936.     IF S1 = S2 THEN ExpSel:= 3
  937.     ELSE ExpSel:= 1;
  938.     
  939.     P.H:= 80;
  940.     P.V:= 70;
  941.     
  942.     SFPPutFile(P,'Save Text-Only As:','Untitled',@ExpGet,FileReply,ExportDLG,
  943.                     NIL);
  944.     
  945.     ForceUpdate;
  946.     GetMyWS(FrontWindow);
  947.  
  948.     IF FileReply.Good THEN
  949.     BEGIN
  950.        FileName:= FileReply.fName;
  951.  
  952.        IF ExpSel = 1  { Selected Text Only }
  953.        THEN CH:= WSGetSelText(WS)
  954.        ELSE CH:= WSGetText(WS);
  955.        
  956.        IF OpFailed THEN EXIT(DoExport);
  957.        
  958.        SetMouse(4);
  959.        fVol:= FileReply.vRefNum;
  960.  
  961.        Error:= FSDelete(FileName,fVol);  { Delete any old }
  962.        Error:= Create(FileName,fVol,'WSDP','TEXT');
  963.        Error:= FSOpen(FileName,fVol,fRef);
  964.  
  965.        fSize:= GetHandleSize(CH);    {         Size of handle }
  966.        HLOCK(Handle(CH));                       { Lock down for write }
  967.  
  968.        Error:= FSWRITE(fRef,fSize,Pointer(@CH^^));
  969.  
  970.        DisposHandle(CH);
  971.        Error:= FlushVol(NIL,fVol);
  972.  
  973.        Error:= FSCLOSE(fRef);
  974.  
  975.        InitCursor;
  976.     END;
  977.  END;
  978.  
  979.  
  980. PROCEDURE FixBadFonts;
  981. VAR Pos,Count,WSize:LongInt;
  982.     Fmt:FormatRec;
  983.     F1,F2,F3:STR255;
  984.     P:Fixed;
  985.     i,x,ps:Integer;
  986.     Alerted:Boolean;
  987.     
  988.     FUNCTION FindFont:Boolean;
  989.     VAR    i,v:Integer;
  990.  
  991.     BEGIN
  992.        v:= CountMItems(MENU3);
  993.        FindFont:= TRUE;            { Assume font exists }
  994.        FOR i:= 1 TO V DO
  995.        BEGIN
  996.           GetItem(Menu3,i,F2);
  997.           IF F1 = F2 THEN EXIT(FindFont);
  998.        END;
  999.        
  1000.        FindFont:= FALSE;
  1001.     END;
  1002.     
  1003. BEGIN
  1004.     WSize:= WS^^.tLength;
  1005.     Pos:= 0;
  1006.     Alerted:= FALSE;
  1007.     GetFontName(1,F3);                { Application font }
  1008.     REPEAT
  1009.        x:= WSFindFormatRec(WS,Pos,Count,Fmt);
  1010.        F1:= Fmt.fName;
  1011.        IF NOT FindFont
  1012.        THEN
  1013.        BEGIN
  1014.           IF NOT Alerted THEN
  1015.           BEGIN
  1016.              SetMouse(0);
  1017.              x:= CautionAlert(BadFonts,NIL);
  1018.           END;
  1019.           Alerted:= TRUE;
  1020.           WSFixFonts(WS,F1,F3,LongInt(0),LongInt(0)); { Fix NAME only }
  1021.        END
  1022.        ELSE
  1023.        BEGIN
  1024.           GetFNum(F1,X);        { Find font num }
  1025.           ps:= HiWord(LongInt(Fmt.fPoint));
  1026.           p:= FixRatio(ps,1);
  1027.           IF NOT RealFont(X,ps) THEN i:= 0 ELSE i:= 1;
  1028.           IF Fmt.fReal = 0 THEN X:= 0 ELSE X:= 1;
  1029.           
  1030.           X:= X+i;
  1031.           IF X = 1  { IF not noth real or both unreal }
  1032.           THEN WSFixFonts(WS,F1,'',p,LongInt(0));
  1033.        END;
  1034.        
  1035.        Pos:= Pos+Count;
  1036.     UNTIL Pos >= WSize;
  1037. END;
  1038.         
  1039.  
  1040.  
  1041. PROCEDURE OpenMain(UseWS:WSHandle; Fmt:FormatPtr);
  1042.     { Opens a window and creates a new WS }
  1043. VAR TempWS:MyWSPtr;
  1044.     TheView,TheBounds:Rect;
  1045.     GH,GV:Integer;
  1046.     
  1047. BEGIN
  1048.     MainWindow:= GetNewWindow(256,NIL,Pointer(-1));
  1049.     
  1050.     IF UseWS = NIL
  1051.     THEN
  1052.     BEGIN  { Wants a new one }
  1053.         ShowWindow(MainWindow);
  1054.         SetPort(MainWindow);
  1055.         MakeNewControls(MainWindow);
  1056.         
  1057.         TheView:= MainWindow^.PortRect;                  { Default to vis area }
  1058.         TheView.Right:= CurWS.vCTL^^.contrlRect.Left; { This becomes right edge }
  1059.         TheView.Bottom:= CurWS.hCTL^^.contrlRect.Top; { Becomes bottom }
  1060.         
  1061.         TheBounds:= TheView;                        { Make a copy }
  1062.         InsetRect(TheBounds,4,2);                    { So it looks nicer }
  1063.         TheView.Left:= TheView.Left+4;                { View should never be > bounds }
  1064.         MyBounds.Left:= TheBounds.Left;                { Translate to longInt }
  1065.         MyBounds.Top:= TheBounds.Top;
  1066.         MyBounds.Right:= TheBounds.Right;
  1067.         MyBounds.Bottom:= TheBounds.Bottom;
  1068.         
  1069.         WS:= WSNew(TheView,MyBounds,DefFlags,NIL,Fmt);
  1070.     END
  1071.     ELSE
  1072.     BEGIN
  1073.        WS:= UseWS;
  1074.        TheView:= MainWindow^.PortRect;
  1075.        TheView.Right:= TheView.Right-15;
  1076.        TheView.Bottom:= TheView.Bottom-15;
  1077.        
  1078.        GH:= TheView.Right-WS^^.tRect.Right;
  1079.        GV:= TheView.Bottom-WS^^.tRect.Bottom;
  1080.        
  1081.        IF (GH <> 0) OR (GV <> 0)
  1082.        THEN
  1083.        BEGIN
  1084.            GH:= WS^^.tRect.Right+15;
  1085.            GV:= WS^^.tRect.Bottom+15;
  1086.            SizeWindow(MainWindow,GH,GV,FALSE);     { So it matches original file }
  1087.        END;
  1088.        
  1089.        ShowWindow(MainWindow);
  1090.        SetPort(MainWindow);
  1091.        FixBadFonts;
  1092.        MakeNewControls(MainWindow);
  1093.     END;
  1094.     
  1095.     TempWS:= MyWsPtr(NewPtr(SizeOf(CurWS)));
  1096.     TempWS^.WS:= WS;
  1097.     TempWS^.Change:= FALSE;
  1098.     TempWS^.fRef:= 0;
  1099.     TempWS^.vRef:= 0;
  1100.     TempWS^.Undo:= 0;
  1101.     TempWS^.unSel1:= 0;
  1102.     TempWS^.unSel2:= 0;
  1103.     TempWS^.unSel3:= 0;
  1104.     TempWS^.hOffset:= 0;
  1105.     TempWS^.vOffset:= 0;
  1106.     TempWS^.vCTL:= CurWS.vCTL;
  1107.     TempWS^.hCTL:= CurWS.hCTL;
  1108.     SetWRefCon(MainWindow,LongInt(TempWS));
  1109.     BlockMove(Ptr(TempWS),Ptr(@CurWS),SizeOf(CurWS));
  1110. END;
  1111.  
  1112.  
  1113. PROCEDURE MenuEnable;   { Called prior to Track menus }
  1114. VAR i:Integer;
  1115.     S1,S2:LongInt;
  1116.     
  1117.     PROCEDURE DisableAll(M:MenuHandle);
  1118.     VAR i:Integer;
  1119.     BEGIN
  1120.        FOR i:= 1 TO 16 DO DisableItem(M,i);
  1121.     END;
  1122.     
  1123.     PROCEDURE EnableAll(M:MenuHandle);
  1124.     VAR i:Integer;
  1125.     BEGIN
  1126.        FOR i:= 1 TO 16 DO EnableItem(M,i);
  1127.     END;
  1128.  
  1129.  
  1130. BEGIN
  1131.     GetMyWS(FrontWindow);
  1132.     
  1133.     IF MainWindow = NIL
  1134.     THEN
  1135.     BEGIN
  1136.        EnableAll(Menu1);
  1137.        EnableAll(Menu2);
  1138.        DisableAll(Menu3);
  1139.        DisableAll(Menu4);
  1140.        DisableAll(Menu5);
  1141.        DisableAll(Menu6);
  1142.        DisableAll(Menu7);
  1143.        
  1144.        DisableItem(Menu1,3);
  1145.        DisableItem(Menu1,4);
  1146.        DisableItem(Menu1,5);
  1147.        DisableItem(Menu1,7);
  1148.        DisableItem(Menu1,8);
  1149.        DisableItem(Menu1,11);            { No Print }
  1150.        
  1151.        DisableItem(Menu1,6);
  1152.        DisableItem(Menu1,9);
  1153.     END
  1154.     ELSE
  1155.     BEGIN
  1156.        EnableAll(Menu1);
  1157.        EnableAll(Menu2);
  1158.        EnableAll(Menu3);
  1159.        EnableAll(Menu4);
  1160.        EnableAll(Menu5);
  1161.        EnableAll(Menu6);
  1162.        EnableAll(Menu7);
  1163.      
  1164.        IF CurWS.Undo = 0 THEN DisableItem(Menu2,1);
  1165.        WSGetSelect(WS,S1,S2);
  1166.        IF S1 = S2
  1167.        THEN
  1168.        BEGIN
  1169.           DisableItem(Menu2,3);        { No Cut }
  1170.           DisableItem(Menu2,4);        { No copy }
  1171.           DisableItem(Menu2,6);        { No Clear }
  1172.        END;
  1173.  
  1174.        XScrap:= InfoScrap;
  1175.        IF (ScrapWS = NIL) AND (XScrap^.scrapCount = MyScrapNum)
  1176.        THEN DisableItem(Menu2,5);
  1177.        
  1178.        IF WSColorEnable THEN EnableItem(Menu4,10)
  1179.        ELSE DisableItem(Menu4,10);
  1180.     END;
  1181. END;
  1182.  
  1183.  
  1184. PROCEDURE SetRealFonts (fName:STR255);
  1185. VAR fNum:Integer;
  1186.  
  1187.  
  1188.      PROCEDURE MarkItem (m,s:Integer);
  1189.      BEGIN
  1190.          IF RealFont(fNum,s) THEN SetItemStyle(Menu5,m,[OUTLINE])
  1191.          ELSE SetItemStyle(Menu5,m,[]);
  1192.      END;
  1193.      
  1194. BEGIN
  1195.    GetFNum(fName,fNum);                { Get font number }
  1196.    MarkItem(1,6);
  1197.    MarkItem(2,9);
  1198.    MarkItem(3,10);
  1199.    MarkItem(4,12);
  1200.    MarkItem(5,14);
  1201.    MarkItem(6,16);
  1202.    MarkItem(7,18);
  1203.    MarkItem(8,20);
  1204.    MarkItem(9,22);
  1205.    MarkItem(10,24);
  1206. END;
  1207.  
  1208.  
  1209. PROCEDURE MarkMenus;
  1210. VAR i,v,TrueStyle,AnyStyle:Integer;
  1211.     Dummy:Boolean;
  1212.     fName,mName:STR255;
  1213.     pSize:Fixed;
  1214.     AllSpaces,AnySpaces,UserSpaces:LongInt;
  1215.     Fmt:FormatRec;
  1216.     
  1217. BEGIN
  1218.    mName:= 'Can t Undo';
  1219.    mName[4]:= CHR(39);            { Apost. }
  1220.       
  1221.    GetMyWS(FrontWindow);
  1222.    
  1223.    IF (ClipWindow <> NIL) AND (FrontWindow = ClipWindow)
  1224.    THEN SetItem(MENU2,9,'Hide Clipboard')
  1225.    ELSE SetItem(MENU2,9,'Show Clipboard');
  1226.  
  1227.    IF MainWindow <> NIL
  1228.    THEN
  1229.    BEGIN
  1230.       { There is an opened WSHandle }
  1231.       { Edit }
  1232.       
  1233.       IF CurWS.Undo < 9
  1234.       THEN
  1235.       BEGIN
  1236.          CASE CurWS.Undo OF
  1237.             
  1238.             1: mName:= 'Undo Format Change';
  1239.             2: mName:= 'Undo Import';
  1240.             3: mName:= 'Undo Cut';
  1241.             4: mName:= 'Undo Copy';
  1242.             5: mName:= 'Undo Paste';
  1243.             6: mName:= 'Undo Clear';
  1244.             7: mName:= 'Undo Selection';
  1245.             8: mName:= 'Undo Backspace';
  1246.          END;
  1247.       END
  1248.       ELSE mName:= 'Undo Typing';
  1249.       
  1250.       SetItem(Menu2,1,mName);
  1251.       
  1252. { Format }
  1253.        
  1254.        v:= WSGetJust(WS);
  1255.        FOR i:= 0 TO 3 DO
  1256.        BEGIN
  1257.            IF i = v THEN CheckItem(Menu6,i+1,TRUE)
  1258.            ELSE CheckItem(Menu6,i+1,FALSE);
  1259.        END;
  1260.        
  1261. { Style }
  1262.  
  1263.        FOR i:= 1 TO 10 DO CheckItem(Menu4,i,FALSE);        { Remove all checkmarks }
  1264.        Dummy:= WSGetStyle(WS,TrueStyle,AnyStyle);
  1265.        
  1266.        IF (TrueStyle = 0) AND (AnyStyle = 0)  { If both are zero }
  1267.        THEN CheckItem(Menu4,1,TRUE)
  1268.        ELSE
  1269.        BEGIN
  1270.           v:= 1;            { To test bits }
  1271.           FOR i:= 2 TO 10 DO
  1272.           BEGIN
  1273.              IF BitAnd(TrueStyle,v) = v
  1274.              THEN CheckItem(Menu4,i,TRUE);
  1275.              v:= v*2;
  1276.           END;
  1277.        END;
  1278.  
  1279. { Font }
  1280.  
  1281.        v:= CountMItems(MENU3);
  1282.        FOR i:= 1 TO v DO CheckItem(Menu3,i,FALSE); { Remove all checkmarks }
  1283.        fName:= ' ';                { Initialize pascal string }
  1284.        
  1285.        IF WSGetFont(WS,fName)   { If all fonts identical }
  1286.        THEN
  1287.        BEGIN
  1288.            i:= 1;
  1289.            REPEAT
  1290.               GetItem(Menu3,i,mName);
  1291.               IF mName = fName
  1292.               THEN
  1293.               BEGIN
  1294.                  CheckItem(Menu3,i,TRUE);
  1295.                  i:= v+1;                { Forces loop to terminate }
  1296.               END
  1297.               ELSE i:= i+1;
  1298.            UNTIL (i > v);
  1299.            
  1300.            SetRealFonts(fName);            { Outline appropriate menus }
  1301.        END
  1302.        ELSE
  1303.        BEGIN
  1304.           For i:= 1 To 10 DO SetItemStyle(Menu5,i,[]);  { NO OUTLINES }
  1305.        END;
  1306.  
  1307.   
  1308. { Point Size }
  1309.  
  1310.        FOR i:= 1 To 16 DO CheckItem(Menu5,i,FALSE);
  1311.        
  1312.        IF WSGetPoint(WS,pSize)
  1313.        THEN
  1314.        BEGIN
  1315.           v:= HiWord(LongInt(pSize));
  1316.           i:= 11;                { Assume none are selected }
  1317.           CASE v OF
  1318.              6: i:= 1;
  1319.              9: i:= 2;
  1320.              10: i:= 3;
  1321.              12: i:= 4;
  1322.              14: i:= 5;
  1323.              16: i:= 6;
  1324.              18: i:= 7;
  1325.              20: i:= 8;
  1326.              22: i:= 9;
  1327.              24: i:= 10;
  1328.           END;
  1329.           
  1330.           CheckItem(Menu5,i,TRUE);
  1331.  
  1332.   { Use Styles }
  1333.   
  1334.             FOR i:= 1 TO 16 DO CheckItem(Menu7,i,FALSE);
  1335.           
  1336.           UserSpaces:= WSGetUserSpace (WS,AllSpaces,AnySpaces);
  1337.           
  1338.           i:= LoWord(AllSpaces);
  1339.          
  1340.           IF BitAnd(i,1) = 1 THEN CheckItem(MENU7,3,TRUE);
  1341.           IF BitAnd(i,2) = 2 THEN CheckItem(MENU7,4,TRUE);
  1342.           IF BitAnd(i,8) = 8 THEN CheckItem(MENU7,5,TRUE);
  1343.           IF BitAnd(i,16) = 16 THEN CheckItem(MENU7,6,TRUE);
  1344.           IF BitAnd(i,32) = 32 THEN CheckItem(MENU7,7,TRUE);
  1345.           IF BitAnd(i,64) = 64 THEN CheckItem(MENU7,8,TRUE);
  1346.  
  1347.        END;
  1348.    END
  1349.    ELSE SetItem(Menu2,1,mName);
  1350.  
  1351. END;
  1352.  
  1353.  
  1354.  
  1355. { The following is a filter to select either "standard" or "text" files. }
  1356.  
  1357. FUNCTION ImpFilter(P:ParmBlkPtr):Boolean;
  1358. BEGIN
  1359.  
  1360.  { This is the I/O filter for IMPORT }
  1361.  
  1362.    CASE OpenSelect OF
  1363.  
  1364.       1: IF (P^.ioFlFndrInfo.fdType = 'WSDC')  { Our own invention }
  1365.           THEN ImpFilter:= FALSE
  1366.           ELSE ImpFilter:= TRUE;
  1367.  
  1368.       2:   IF P^.ioFlFndrInfo.fdType = 'TEXT'    { Raw TEXT }
  1369.             THEN ImpFilter:= FALSE
  1370.             ELSE ImpFilter:= TRUE;
  1371.    END;
  1372. END;
  1373.  
  1374.  
  1375. { This is the DialogProc for IMPORT }
  1376.  
  1377. FUNCTION ImpGet(Item:Integer; theDialog:DialogPtr):Integer;
  1378. VAR CT1,CT2:Handle;
  1379.     T,X,Val:Integer;
  1380.     R:RECT;
  1381.     ByCode:STR255;
  1382.  
  1383. BEGIN
  1384.    ImpGet:= ITEM;
  1385.  
  1386.    IF ITEM = -1 THEN  { TIME TO INITIALIZE! }
  1387.    BEGIN
  1388.       FOR X:= 1 TO 2 DO
  1389.       BEGIN
  1390.          GetDItem(theDialog,X+10,T,CT1,R);
  1391.          IF X = OpenSelect  { If this one selected }
  1392.          THEN Val:= 1
  1393.          ELSE Val:= 0;
  1394.          SetCTLValue(ControlHandle(CT1),Val);
  1395.       END;
  1396.    END
  1397.    ELSE
  1398.    BEGIN
  1399.       IF (Item > 10) AND (Item < 13) THEN
  1400.       BEGIN
  1401.          FOR X:= 11 TO 12 DO
  1402.          BEGIN
  1403.             GetDItem(theDialog,X,T,CT1,R);
  1404.             IF X = Item THEN Val:= 1 ELSE Val:= 0;
  1405.             SetCTLValue(ControlHandle(CT1),Val);  { Set if THIS FILE  }
  1406.          END;
  1407.          
  1408.          OpenSelect:= Item-10;
  1409.          ImpGet:= 101;        { Force a re-display }
  1410.       END
  1411.    END;
  1412. END;
  1413.  
  1414.  
  1415. PROCEDURE MakeMonaco (VAR Fmt:FormatRec);
  1416. VAR x:Integer;
  1417. BEGIN
  1418.    Fmt.Pos:= 0;
  1419.    Fmt.UserProcs:= NIL;
  1420.    Fmt.fReal:= 1;
  1421.    FOR X:= 1 TO 31 DO Fmt.fName[X]:= CHR(0);
  1422.    Fmt.fName:= 'Monaco';
  1423.    Fmt.fStyle:= 0;
  1424.    Fmt.fPoint:= FixRatio(9,1);
  1425.    Fmt.fgColor.Red:= 0;
  1426.    Fmt.fgColor.Green:= 0;
  1427.    Fmt.fgColor.Blue:= 0;
  1428.    Fmt.Txr:= 0;
  1429.    Fmt.cExtra:= LongInt(0);
  1430.    Fmt.Leading:= 0;
  1431.    Fmt.UserSpace:= 0;
  1432. END;
  1433.  
  1434. { Open a unique file }
  1435.  FUNCTION OpenFile(inName:STR255; inVol:Integer):Boolean;
  1436.  VAR FileReply:SFReply;
  1437.      fSize,Position,Count:LongInt;
  1438.      Fmt:FormatRec;
  1439.      Error,Error1,fRef,fVol,x:Integer;
  1440.      FileName:STR255;
  1441.      DataHandle:Handle;
  1442.      cDataHandle:Handle;
  1443.      FTypes:SFTypeList;
  1444.      P:Point;
  1445.  
  1446.  BEGIN
  1447.      P.H:= 40;
  1448.      P.V:= 60;
  1449.      FTypes[0]:= 'WSDC';
  1450.      FTypes[1]:= 'TEXT';
  1451.      
  1452.      IF Length(InName) > 0 THEN
  1453.      BEGIN
  1454.         FileReply.fName:= inName;
  1455.         FileReply.vRefNum:= inVol;
  1456.         FileReply.Good:= TRUE;
  1457.         OpenSelect:= 1;
  1458.      END
  1459.      ELSE SFPGetFile(P,' ',@ImpFilter,2,FTypes,@ImpGET,FileReply,OpenDLG,NIL);
  1460.  
  1461.      IF FileReply.Good  { If accepted } THEN
  1462.      BEGIN
  1463.         FileName:= FileReply.fName;
  1464.         fVol:= FileReply.vRefNum;
  1465.  
  1466.         IF OpenSelect = 2   { IF TEXT FILE }
  1467.         THEN
  1468.         BEGIN
  1469.             IF NOT GetWrapType THEN EXIT(OpenFile);
  1470.  
  1471.             SetMouse(4);
  1472.  
  1473.         { See if line edit mode }
  1474.         
  1475.             IF DefFlags = NoWrap { IF LINE-EDIT }
  1476.             THEN
  1477.             BEGIN
  1478.                MakeMonaco(Fmt);
  1479.                OpenMain(NIL,@Fmt);
  1480.             END
  1481.             ELSE OpenMain(NIL,NIL);
  1482.             
  1483.             Error:= FSOpen(FileName,fVol,fRef);
  1484.             Error:= GetEOF(fRef,fSize);         { Get logical file size }
  1485.     
  1486.             cDataHandle:= NewHandle(fSize);
  1487.             HLOCK(cDataHandle);
  1488.     
  1489.             Error:= FSRead(fRef,fSize,Pointer(@cDataHandle^^));
  1490.             HUNLOCK(cDataHandle);
  1491.     
  1492.             Error:= FSClose(fRef);
  1493.             
  1494.             SetPort(MainWindow);
  1495.     
  1496.             WSSetText(WS,cDataHandle);
  1497.             DisposHandle(cDataHandle);        
  1498.         END
  1499.         ELSE
  1500.         BEGIN
  1501.  
  1502.             SetMouse(4);
  1503.  
  1504.             Error:= FSOpen(FileName,fVol,fRef);
  1505.     
  1506.             Error:= GetEOF(fRef,fSize);         { Get logical file size }
  1507.     
  1508.             DataHandle:= NewHandle(fSize);
  1509.             HLOCK(DataHandle);
  1510.     
  1511.             Error:= FSRead(fRef,fSize,Pointer(@DataHandle^^));
  1512.             HUNLOCK(DataHandle);
  1513.     
  1514.             Error:= FSClose(fRef);
  1515.             
  1516.             WS:= HandleToWS(DataHandle);    { Turn it into a WSHandle }
  1517.             DisposHandle(DataHandle);
  1518.  
  1519.             OpenMain(WS,NIL);
  1520.             SetWTitle(MainWindow,FileName);  { Show new title }
  1521.             CurWS.vRef:= fVol;
  1522.  
  1523.  { Determine scroll positions }
  1524.              
  1525.             WSGetScrollState(WS,CurWS.hOffset,CurWS.vOffset);
  1526.  
  1527.             x:= CurWS.vOffset DIV 8;
  1528.             SetCTLValue(CurWS.vCTL,X);
  1529.             X:= CurWS.hOffset DIV 8;
  1530.             SetCTLValue(CurWS.hCTL,X);
  1531.         END;
  1532.  
  1533.         SetPort(MainWindow);
  1534.         SetMyWS(MainWindow);
  1535.  
  1536.         OpenFile:= TRUE;
  1537.         ForceUpdate;
  1538.         GetMyWS(FrontWindow);
  1539.         SetMaxScroll;
  1540.         ShowControl(CurWS.vCTL);
  1541.         ShowControl(CurWS.hCTL);
  1542.      END
  1543.      ELSE OpenFile:= FALSE;
  1544.  END;
  1545.  
  1546.  
  1547. { SAVE FILE ROUTINES }
  1548.  
  1549.  FUNCTION SaveFile(fVol:Integer):Boolean;
  1550.  
  1551.  VAR FileReply:SFREPLY;
  1552.      P:Point;
  1553.      FileName:STR255;
  1554.      DataHandle:Handle;
  1555.      Error,Error1,Error2,fRef:Integer;
  1556.      FSize:LongInt;
  1557.  
  1558.  BEGIN
  1559.       CaretOff;
  1560.  
  1561.       GetWTitle(MainWindow,FileName);       { Get file "name" }
  1562.       FileReply.fName:= FileName;       { Assume a mere SAVE }
  1563.  
  1564.       IF fVol = 0  { If this is a new guy } THEN
  1565.       BEGIN
  1566.          P.H:= 80;
  1567.          P.V:= 100;
  1568.          CaretOff;
  1569.          SFPutFile(P,'Save Document As:',FileName,NIL,FileReply);
  1570.          fVol:= FileReply.vRefNum;
  1571.       END
  1572.       ELSE FileReply.Good:= TRUE;   { Fake out the "ACCEPT" }
  1573.  
  1574.       IF FileReply.Good THEN
  1575.       BEGIN
  1576.          ForceUpdate;
  1577.          GetMyWS(FrontWindow);
  1578.          SetMouse(4);
  1579.          DataHandle:= WSToHandle(WS);     { Get a handle structure }
  1580.          
  1581.          IF OpFailed THEN
  1582.          BEGIN
  1583.             SaveFile:= FALSE;
  1584.             EXIT(SaveFile);
  1585.          END;
  1586.          
  1587.          FileName:= FileReply.fName;
  1588.  
  1589.          Error:= FSDelete(FileName,fVol);  { Delete any old }
  1590.          Error:= Create(FileName,fVol,'WSDP','WSDC');
  1591.          Error:= FSOpen(FileName,fVol,fRef);
  1592.  
  1593.          fSize:= GetHandleSize(DataHandle);    { Size of handle }
  1594.          HLOCK(DataHandle);               { Lock down for write }
  1595.  
  1596.          Error1:= FSWRITE(fRef,fSize,Pointer(@DataHandle^^));
  1597.  
  1598.          DisposHandle(DataHandle);
  1599.          Error2:= FlushVol(NIL,fVol);
  1600.  
  1601.          Error:= FSCLOSE(fRef);
  1602.  
  1603.          InitCursor;
  1604.  
  1605.          IF (Error1 = 0) AND (Error2 = 0)  { If no file errors }
  1606.          THEN
  1607.          BEGIN
  1608.             SetWTitle(MainWindow,FileName);  { Show new title }
  1609.             CurWS.vRef:= fVol;
  1610.             CurWS.Change:= FALSE;
  1611.             SetMyWS(MainWindow);
  1612.          END
  1613.          ELSE FileReply.Good:= FALSE;
  1614.       END;
  1615.  
  1616.       SaveFile:= FileReply.Good;
  1617.  END;
  1618.  
  1619.  
  1620. FUNCTION CloseMain:Boolean;
  1621. VAR TempWS:MyWSPtr;
  1622.     io:Integer;
  1623.     
  1624. BEGIN
  1625.    CloseMain:= FALSE;                { Assume not OK to close }
  1626.    IF CurWS.Change
  1627.    THEN
  1628.    BEGIN
  1629.       CaretOff;
  1630.       SetMouse(0);
  1631.       io:= CautionAlert(SaveChanges,NIL);
  1632.       
  1633.       ForceUpdate;
  1634.       GetMyWS(FrontWindow);
  1635.  
  1636.       IF io = 1  { "YES" }
  1637.       THEN
  1638.       BEGIN
  1639.          IF NOT SaveFile(CurWS.vRef)
  1640.          THEN EXIT(CloseMain);
  1641.       END
  1642.       ELSE
  1643.       IF io = 2  { "CANCEL" }
  1644.       THEN EXIT(CloseMain);
  1645.    END;
  1646.    
  1647.    CloseMain:= TRUE;
  1648.    WSDispose(WS);
  1649.    TempWS:= MyWSPtr(GetWRefCon(MainWindow));
  1650.    DisposPtr(Ptr(TempWS));
  1651.    DisposeWindow(MainWindow);
  1652.    MainWindow:= NIL;
  1653. END;
  1654.  
  1655.  
  1656.  
  1657.   {  PRINT ROUTINE }
  1658.   
  1659.   
  1660.  Procedure PrintWS(WS:WSHandle);
  1661.  VAR PageRect:Rect;
  1662.      Position:LongInt;
  1663.      
  1664.  BEGIN
  1665.     PageRect:= PHDL^^.PrInfo.rPage;
  1666.     
  1667.      PrintPort:= PrOpenDoc(PHDL,NIL,NIL);
  1668.     
  1669.     CXL:= FALSE;
  1670.     
  1671.     PrSetError(0);
  1672.     
  1673.     REPEAT
  1674.        PrOpenPage(PrintPort,NIL);
  1675.        Position:= WSPrint(WS,Position,PageRect);
  1676.        IF PrError = 128 THEN CXL:= TRUE;
  1677.        PrClosePage(PrintPort);
  1678.     UNTIL (Position = -1) OR (CXL);
  1679.     
  1680.     PrCloseDoc(PrintPort);
  1681.     
  1682.     IF NOT CXL THEN PrPicFile(PHDL,NIL,NIL,NIL,PStatus);
  1683.  END;
  1684.  
  1685.  
  1686.  {  MENUS }
  1687.  
  1688.  
  1689.  PROCEDURE DoFileMenu (Item:Integer);
  1690.  VAR Dummy,OK2Quit:Boolean;
  1691.      W:WindowPtr;
  1692.      Fmt:FormatRec;
  1693.      
  1694.  BEGIN
  1695.     GetMyWS(FrontWindow);
  1696.  
  1697.     Case Item OF
  1698.       
  1699.       1: { NEW }
  1700.             BEGIN
  1701.              IF NOT GetWrapType THEN EXIT(DoFileMenu);
  1702.              IF DefFlags = NoWrap
  1703.              THEN
  1704.              BEGIN
  1705.                 MakeMonaco(Fmt);
  1706.                 OpenMain(NIL,@Fmt);
  1707.              END
  1708.              ELSE OpenMain(NIL,NIL);
  1709.  
  1710.              ForceUpdate;
  1711.              GetMyWS(FrontWindow);
  1712.              SetMaxScroll;
  1713.              ShowControl(CurWS.vCTL);
  1714.              ShowControl(CurWS.hCTL);
  1715.           END;
  1716.  
  1717.       2: { OPEN } Dummy:= OpenFile('',0);
  1718.       
  1719.       3: { CLOSE } IF MainWindow <> NIL THEN Dummy:= CloseMain;
  1720.       
  1721.       4: { Save } Dummy:= SaveFile(CurWS.vRef);
  1722.       
  1723.       5: { Save As } Dummy:= SaveFile(0);
  1724.       
  1725.       7: { Import Text File } DoImport;
  1726.       
  1727.       8: { Save As Text } DoExport;
  1728.       
  1729.       10: { Page Setup }
  1730.           BEGIN
  1731.              ReHabPrint;
  1732.              SetMouse(0);
  1733.              Dummy:= PrStlDialog(PHDL);
  1734.           END;
  1735.       
  1736.       11: { Print }
  1737.           BEGIN
  1738.              ReHabPrint;
  1739.              SetMouse(0);
  1740.              IF PrJobDialog(PHDL)
  1741.              THEN
  1742.              BEGIN
  1743.                 SetMouse(4);
  1744.                 ForceUpdate;
  1745.                 GetMyWS(FrontWindow);
  1746.                 PrintWS(WS);
  1747.              END;
  1748.           END;
  1749.             
  1750.       13: BEGIN
  1751.              OK2Quit:= FALSE;
  1752.                REPEAT
  1753.                 GetMyWS(FrontWindow);
  1754.                 IF MainWindow = NIL
  1755.                 THEN OK2Quit:= TRUE
  1756.                 ELSE IF NOT CloseMain THEN EXIT(DoFileMenu);   { Audios }
  1757.                 ForceUpdate;
  1758.              UNTIL OK2Quit;
  1759.              IF What4Scrap THEN
  1760.              BEGIN
  1761.                 WSShutDown;
  1762.                 ExitToShell;
  1763.              END;
  1764.           END;
  1765.     End;
  1766.  END;
  1767.  
  1768.  
  1769.  PROCEDURE DoFontMenu (Item:Integer);
  1770.  VAR fStr:STR255;
  1771.  
  1772.  BEGIN
  1773.     GetMyWS(FrontWindow);
  1774.     IF MainWindow = NIL THEN EXIT(DoFontMenu);
  1775.  
  1776.     SetFontUndo;                        { Establish an UNDO for this }
  1777.     
  1778.     GetItem(Menu3,Item,fStr);            { Return the actual font name }
  1779.     IF WSSetFont(WS,fStr)                { If needs rebuild .. }
  1780.        THEN ReDisplay;                    { Recalc/Redisplay }
  1781.     
  1782.     SetChanges(TRUE);
  1783.  END;
  1784.  
  1785.  
  1786.  
  1787.  FUNCTION MakeYourOwn:Integer;
  1788.  VAR V:Integer;
  1789.     PS:Fixed;
  1790.  
  1791.     BEGIN
  1792.        IF WSGetPoint(WS,PS)
  1793.        THEN V:= HiWord(LongInt(PS))
  1794.        ELSE V:= 12;
  1795.        IF NumDialog(PtSizeDLG,V)
  1796.        THEN MakeYourOwn:= V
  1797.        ELSE MakeYourOwn:= 0;
  1798.        
  1799.        SetPort(MainWindow);
  1800.     END;
  1801.     
  1802.  
  1803.  
  1804.  PROCEDURE DoPointMenu (Item:Integer);
  1805.  VAR PF:Fixed;
  1806.       P:Integer;
  1807.  
  1808.  BEGIN
  1809.     GetMyWS(FrontWindow);
  1810.     IF MainWindow = NIL THEN EXIT(DoPointMenu);
  1811.  
  1812.     SetFontUndo;
  1813.     
  1814.     CASE Item OF
  1815.        
  1816.        1: P:= 6;
  1817.        2: P:= 9;
  1818.        3: P:= 10;
  1819.        4: P:= 12;
  1820.        5: P:= 14;
  1821.        6: P:= 16;
  1822.        7: P:= 18;
  1823.        8: P:= 20;
  1824.        9: P:= 22;
  1825.        10: P:= 24;
  1826.        11: P:= MakeYourOwn;
  1827.    END;
  1828.  
  1829.    IF P > 0 THEN
  1830.    BEGIN
  1831.       PF:= FixRatio(P,1);    { Make a whole amount }
  1832.       IF WSSetPoint(WS,PF) THEN Redisplay;
  1833.       SetChanges(TRUE);
  1834.       
  1835.    END;
  1836.  END;
  1837.  
  1838.  
  1839.  
  1840.  PROCEDURE DoEditMenu (Item:Integer);
  1841.  VAR Dummy:Boolean;
  1842.      Sel1,Sel2:LongInt;
  1843.      TempFonts:FormatHandle;
  1844.  
  1845.     PROCEDURE UndoClear;
  1846.     BEGIN
  1847.          IF UndoWS = NIL THEN EXIT(UndoClear);
  1848.  
  1849.          SetMouse(4);
  1850.          WSSetSelect(WS,CurWS.UnSel1,CurWS.UnSel1,FALSE);
  1851.          Dummy:= WSPaste(UndoWS,WS);
  1852.          IF OpFailed THEN EXIT(UndoClear);
  1853.          WSDispose(UndoWS);            { Remove Undo }
  1854.          UndoWS:= NIL;
  1855.          ReDisplay;
  1856.          WSSetSelect(WS,CurWS.UnSel1,CurWS.UnSel2,TRUE);
  1857.          CurWS.Undo:= 0;
  1858.     END;
  1859.     
  1860.     PROCEDURE UndoPaste;
  1861.       BEGIN
  1862.          SetMouse(4);
  1863.          WSSetSelect(WS,CurWS.UnSel1,CurWS.UnSel2,FALSE);
  1864.          Dummy:= WSCut(WS);
  1865.          CurWS.Undo:= 0;
  1866.          ReDisplay;
  1867.          ForceScroll;
  1868.       END;
  1869.  
  1870.     
  1871.  BEGIN
  1872.     GetMyWS(FrontWindow);
  1873.     IF MainWindow = NIL THEN
  1874.     BEGIN
  1875.        IF Item < 7 THEN Dummy:= SystemEdit(Item-1)
  1876.        ELSE
  1877.        IF Item = 9 THEN ShowClipBoard;
  1878.     END
  1879.     ELSE
  1880.     BEGIN
  1881.         IF Item > 1 { IF NOT NOW 'UNDO' }
  1882.         THEN WSGetSelect(WS,CurWS.unSel1,CurWS.unSel2);        { Get selection }
  1883.                 
  1884.         CASE Item OF
  1885.           
  1886.           1:  { Undo }
  1887.               BEGIN
  1888.                  IF CurWS.Undo < 8 { If one of my EDIT items }
  1889.                  THEN
  1890.                  BEGIN
  1891.                     CASE CurWS.Undo OF
  1892.                        
  1893.                        1: { Format UNDO }
  1894.                           BEGIN
  1895.                              SetMouse(4);
  1896.                              TempFonts:= WSCopyFormat(WS);    { Get THIS format }
  1897.                              IF OpFailed THEN EXIT(DoEditMenu);
  1898.                              WSSetSelect(WS,CurWS.UnSel1,CurWS.UnSel2,FALSE);
  1899.                              WSApplyFormat(WS,FontScrap);
  1900.                              DisposHandle(Handle(FontScrap));
  1901.                              FontScraP:= TempFonts;
  1902.                              CurWS.Undo:= 1;        { Same as before }
  1903.                              WSBitMapDisplay(WS,0,SrcCopy,TRUE);
  1904.                           END;
  1905.                        
  1906.                        2: { Undo Import } UndoPaste;
  1907.                        
  1908.                        3: { Undo Cut }
  1909.                           BEGIN
  1910.                                SetMouse(4);
  1911.                              WSSetSelect(WS,CurWS.UnSel1,CurWS.UnSel1,FALSE);
  1912.                              Dummy:= WSPaste(ScrapWS,WS);
  1913.                              IF OpFailed THEN EXIT(DoEditMenu);
  1914.                              WSSetSelect(WS,CurWS.UnSel1,CurWS.UnSel2,FALSE);
  1915.                              WSDispose(ScrapWS);        { Remove scrap }
  1916.                              ScrapWS:= UndoWS;            { Old scrap }
  1917.                              UndoWS:= NIL;
  1918.                              CurWS.Undo:= 5;            { Next time undo PASTE }
  1919.                              ReDisplay;
  1920.                              InvalScrap;
  1921.                           END;
  1922.                           
  1923.                        4: { Undo Copy }
  1924.                           BEGIN
  1925.                              WSSetSelect(WS,CurWS.UnSel1,CurWS.UnSel2,TRUE);
  1926.                              WSDispose(ScrapWS);
  1927.                              ScrapWS:= UndoWS;
  1928.                              UndoWS:= NIL;
  1929.                              CurWS.Undo:= 0;  { Don't know how to undo this }
  1930.                              InvalScrap;
  1931.                           END;
  1932.                        
  1933.                        5: { Undo Paste } UndoPaste;
  1934.                           
  1935.                        6: { Undo Clear }
  1936.                              BEGIN
  1937.                                  UndoClear;
  1938.                               CurWS.Undo:= 0;
  1939.                           END;
  1940.                           
  1941.                        7: { Undo SelectAll }
  1942.                           BEGIN
  1943.                              WSSetSelect(WS,CurWS.UnSel1,CurWS.UnSel2,TRUE);
  1944.                              CurWS.Undo:= 0;
  1945.                           END;
  1946.                        END;
  1947.                      END
  1948.                      ELSE
  1949.                      BEGIN
  1950.                 { A KEYSTROKE 'UNDO' }
  1951.                         IF CurWS.UnSel1 <> CurWS.UnSel2  { If there was a selection }
  1952.                         THEN
  1953.                         BEGIN
  1954.                            IF CurWS.Undo <> 8 { If not backspace }
  1955.                            THEN
  1956.                            BEGIN
  1957.                               EV.Message:= 8;
  1958.                               WSKey(WS,EV);  { Fake a backspace }
  1959.                            END;
  1960.                            UndoClear;
  1961.                         END
  1962.                         ELSE
  1963.                         BEGIN
  1964.                 { No selection }
  1965.                            WSGetSelect(WS,CurWS.UnSel1,CurWS.UnSel2);
  1966.                            IF CurWS.UnSel1 <> CurWS.UnSel3
  1967.                            THEN
  1968.                            BEGIN
  1969.                               WSSetSelect(WS,CurWS.unSel3,CurWS.UnSel1,FALSE);
  1970.                               IF UndoWS <> NIL THEN WSDispose(UndoWS);
  1971.                               UndoWS:= WSCopy(WS);        { Copy keys to be deleted }
  1972.                               Dummy:= WSCut(WS);
  1973.                               ReDisplay;
  1974.                               CurWS.Undo:= 6;            { Pretend a CLEAR }
  1975.                               WSGetSelect(WS,CurWS.UnSel1,CurWS.UnSel2);
  1976.                            END;
  1977.                         END;
  1978.                      END;
  1979.                  
  1980.                  SetChanges(TRUE);
  1981.               END;
  1982.               
  1983.  
  1984.           3:  { Cut }
  1985.               BEGIN
  1986.                  SetMouse(4);
  1987.                  IF UndoWS <> NIL THEN WSDispose(UndoWS);
  1988.                  UndoWS:= ScrapWS;
  1989.                  ScrapWS:= WSCopy(WS);
  1990.                  IF OpFailed
  1991.                  THEN
  1992.                  BEGIN
  1993.                     OpFailed:= FALSE;        { So it doesn't re-alert }
  1994.                     SetMouse(0);
  1995.                     CurWS.Undo:= 0;
  1996.                     SetMyWS(MainWindow);
  1997.                     CaretOff;
  1998.                     io:= CautionAlert(CantUndo,NIL);
  1999.                     IF io = 1 THEN EXIT(DoEditMenu);
  2000.                     SetPort(MainWindow);
  2001.                  END
  2002.                  ELSE CurWS.Undo:= 3;
  2003.                  
  2004.                  MyOwnScrap:= TRUE;
  2005.                  
  2006.                  IF WSCut(WS) THEN ReDisplay;
  2007.                  SetChanges(TRUE);
  2008.                  ForceScroll;
  2009.                  InvalScrap;
  2010.               END;
  2011.           
  2012.           4:  { Copy }
  2013.               BEGIN
  2014.                  SetMouse(4);
  2015.                  IF UndoWS <> NIL THEN WSDispose(UndoWS);
  2016.                  UndoWS:= ScrapWS;            { Copy the scrap }
  2017.                  ScrapWS:= WSCopy(WS);
  2018.                  IF OpFailed THEN EXIT(DoEditMenu);
  2019.                  MyOwnScrap:= TRUE;
  2020.                  InvalScrap;
  2021.                  CurWS.Undo:= 4;
  2022.                  SetMyWS(MainWindow);
  2023.               END;
  2024.           
  2025.           5:  { Paste }
  2026.               BEGIN
  2027.                   GetXScrap;                { Get any external scrap }
  2028.                   IF ScrapWS <> NIL
  2029.                   THEN
  2030.                   BEGIN
  2031.                      SetMouse(4);
  2032.                      IF WSPaste(ScrapWS,WS) THEN ReDisplay;
  2033.                      IF OpFailed THEN EXIT(DoEditMenu);
  2034.                      CurWS.Undo:= 5;
  2035.                      WSGetSelect(WS,Sel1,CurWS.unSel2);  { So I can undo paste }
  2036.                      SetChanges(TRUE);
  2037.                      ForceScroll;
  2038.                   END;
  2039.               END;
  2040.           
  2041.           6:  { Clear }
  2042.               BEGIN
  2043.                  SetMouse(4);
  2044.                  IF UndoWS <> NIL THEN WSDispose(UndoWS);
  2045.                  UndoWS:= WSCopy(WS);
  2046.                  
  2047.                  IF OpFailed
  2048.                  THEN
  2049.                  BEGIN
  2050.                     OpFailed:= FALSE;        { So it doesn't re-alert }
  2051.                     SetMouse(0);
  2052.                     CurWS.Undo:= 0;
  2053.                     SetMyWS(MainWindow);
  2054.                     CaretOff;
  2055.                     io:= CautionAlert(CantUndo,NIL);
  2056.                     IF io = 1 THEN EXIT(DoEditMenu);
  2057.                     SetPort(MainWindow);
  2058.                  END
  2059.                  ELSE CurWS.Undo:= 6;
  2060.                  
  2061.                  IF WSCut(WS) THEN ReDisplay;
  2062.                  SetChanges(TRUE);
  2063.                  ForceScroll;
  2064.               END;
  2065.               
  2066.           7:  { Select All }
  2067.               BEGIN
  2068.                    WSSetSelect(WS,0,10000000,TRUE);
  2069.                  CurWS.Undo:= 7;
  2070.                  SetMyWS(MainWindow);
  2071.               END;
  2072.     
  2073.           9:  ShowClipBoard;
  2074.  
  2075.         END;
  2076.         
  2077.     END;
  2078.  END;
  2079.  
  2080.  
  2081.  
  2082.  PROCEDURE PickColor;
  2083.  VAR InColor,OutColor:RGBColor;
  2084.      Title:STR255;
  2085.      P:Point;
  2086.      AnyColor:Integer;
  2087.      
  2088.  BEGIN
  2089.     IF NOT WSGetColor(WS,inColor)
  2090.     THEN
  2091.     BEGIN
  2092.         inColor.Red:= 0;
  2093.         inColor.Green:= 0;
  2094.         inColor.Blue:= 0;
  2095.     END; 
  2096.  
  2097.     P.H:= 0;
  2098.     P.V:= 0;
  2099.     
  2100.     Title:= 'Choose Text Color:';
  2101.     
  2102.     IF GetColor(P,Title,InColor,OutColor)
  2103.     THEN 
  2104.     BEGIN
  2105.        ForceUpdate;
  2106.        SetMyWS(FrontWindow);
  2107.        SetFontUndo;
  2108.        IF WSSetColor(WS,OutColor) THEN ReDisplay;
  2109.        SetChanges(TRUE);
  2110.     END;
  2111.  END;
  2112.  
  2113.  
  2114.  
  2115.  PROCEDURE DoStyleMenu (Item:Integer);
  2116.  VAR TheStyle:Integer;
  2117.      SetStyle1,SetStyle2:Boolean;
  2118.      
  2119.  BEGIN
  2120.     GetMyWS(FrontWindow);
  2121.     IF MainWindow = NIL THEN EXIT(DoStyleMenu);
  2122.     
  2123.     IF Item = 10 { Set Color } THEN PickColor
  2124.     ELSE
  2125.     BEGIN
  2126.         SetFontUndo;
  2127.     
  2128.         CASE Item OF
  2129.            
  2130.            1: TheStyle:= 0;        { Plain }
  2131.            2: TheStyle:= 1;
  2132.            3: TheStyle:= 2;
  2133.            4: TheStyle:= 4;
  2134.            5: TheStyle:= 8;
  2135.            6: TheStyle:= 16;
  2136.            7: TheStyle:= 32;
  2137.            8: TheStyle:= 64;
  2138.            9: TheStyle:= 128;
  2139.         END;
  2140.         
  2141.         SetStyle1:= WSSetStyle(WS,TheStyle);
  2142.         SetStyle2:= FALSE;
  2143.         
  2144.         IF TheStyle = 0  { If this was "plain" }
  2145.         THEN SetStyle2:= WSSetUserStyle(WS,NIL,0,0);   { Clear UserProcs }
  2146.         
  2147.         IF (SetStyle1) OR (SetStyle2) THEN ReDisplay;
  2148.         SetChanges(TRUE);
  2149.     END;
  2150.  END;
  2151.  
  2152.  
  2153.  PROCEDURE DoFormatMenu (Item:Integer);
  2154.  VAR SM:LongInt;
  2155.      err:OSErr;
  2156.  BEGIN
  2157.     GetMyWS(FrontWindow);
  2158.     IF MainWindow = NIL THEN EXIT(DoFormatMenu);
  2159.     WSSetJust(WS,Item-1);
  2160.     WSDisplay(WS,0,TRUE,TRUE);
  2161.     SetChanges(TRUE);
  2162.  END;
  2163.  
  2164.  
  2165.  
  2166.  
  2167.  
  2168.  PROCEDURE DoDemoMenu(Item:Integer);
  2169.  var test1,test2:integer;
  2170.       test3:LongInt;
  2171.      TBuf:TextBlock;
  2172.      WG:WSGlobals;
  2173.      r:LongRect;
  2174.      
  2175.  BEGIN
  2176.     GetMyWS(FrontWindow);
  2177.     IF MainWindow = NIL THEN EXIT(DoDemoMenu);
  2178.  
  2179.     Case Item OF
  2180.           
  2181.           1: io:= Alert(AddOnAlert,NIL);
  2182.           
  2183.     END;
  2184.     
  2185.  END;
  2186.  
  2187.  
  2188.  PROCEDURE DoMenus(MResult:LongInt);
  2189.  VAR io,Item:Integer;
  2190.      MenuStr:STR255;
  2191.  
  2192.  
  2193.  BEGIN
  2194.     Item:= LOWORD(MResult);
  2195.     
  2196.     CASE HiWord(MResult) OF
  2197.  
  2198.          1: { DA's }
  2199.             BEGIN
  2200.                IF Item = 1 THEN io:= Alert(AboutAlert,NIL)
  2201.                ELSE
  2202.                BEGIN
  2203.                   PutXScrap;            { Load external scrap }
  2204.                   GetItem(Menu0,Item,MenuStr);
  2205.                   io:= OpenDeskAcc(MenuSTR);
  2206.                END;
  2207.             END;
  2208.  
  2209.  
  2210.        100: DoFileMenu(Item);        { FILE }
  2211.  
  2212.  
  2213.        200: DoEditMenu(Item);        { EDIT }
  2214.  
  2215.  
  2216.        300: DoFontMenu(Item);        { FONT }
  2217.  
  2218.  
  2219.        400: DoStyleMenu(Item);        { STYLE }
  2220.  
  2221.  
  2222.        500: DoPointMenu(Item);        { Point size }
  2223.  
  2224.  
  2225.        600: DoFormatMenu(Item);        { FORMAT }
  2226.        
  2227.        
  2228.        700: DoDemoMenu(Item);        { Special demo stuff }
  2229.  
  2230.  
  2231.     END;
  2232.  
  2233.  
  2234.     HILITEMENU(0);     { Remove menu hilites }
  2235.  END;
  2236.  
  2237.  
  2238.  
  2239.  
  2240.  PROCEDURE DoKey;
  2241.  VAR KChar:Char;
  2242.      forMenus,bSel,eSel:LongInt;
  2243.      PrevFail:Boolean;
  2244.  
  2245.         FUNCTION AnArrowKey:Boolean;
  2246.         BEGIN
  2247.            IF (BitAnd(LoWord(EV.Message),255) >27)
  2248.            AND (BitAnd(LoWord(EV.Message),255) <32)
  2249.            THEN AnArrowKey:= TRUE
  2250.            ELSE AnArrowKey:= FALSE;
  2251.         END;
  2252.         
  2253.  BEGIN
  2254.  
  2255.  { Meant for WS }
  2256.  
  2257.       IF BitAnd(EV.Modifiers,256) = 256  { IF COMMAND KEY DOWN }
  2258.       THEN
  2259.       BEGIN
  2260.          MenuEnable;          { Enable / Disable appropriate Menu items }
  2261.          KChar:= CHR(LoWord(EV.Message));
  2262.          forMenus:= MenuKey(KChar);
  2263.          DoMenus(forMenus);
  2264.       END
  2265.       ELSE
  2266.       BEGIN
  2267.           GetMyWS(FrontWindow);
  2268.           IF MainWindow <> NIL THEN
  2269.           BEGIN
  2270.              ObscureCursor;
  2271.              
  2272.              IF BitAnd(LoWord(EV.Message),255) = 3  { IF ENTER KEY }
  2273.              THEN EV.Message:= 10;
  2274.  
  2275.              WSGetSelect(WS,CurWS.unSel1,CurWS.unSel2);        
  2276.                                      { To see if there's a selection }
  2277.  
  2278.              IF (CurWS.unSel1 <> CurWS.unSel2)
  2279.              AND (NOT AnArrowKey) { If a selection }
  2280.              THEN
  2281.              BEGIN
  2282.                 SetMouse(4);
  2283.                 IF UndoWS <> NIL THEN WSDispose(UndoWS);    { Remove UNDO }
  2284.                 UndoWS:= WSCopy(WS);                        { Copy for UNDO }
  2285.                 PrevFail:= OpFailed;
  2286.                 IF OpFailed
  2287.                 THEN
  2288.                 BEGIN
  2289.                     OpFailed:= FALSE;        { So it doesn't re-alert }
  2290.                     SetMouse(0);
  2291.                     CurWS.Undo:= 0;
  2292.                     SetMyWS(MainWindow);
  2293.                     CaretOff;
  2294.                     io:= CautionAlert(CantUndo,NIL);
  2295.                     IF io = 1 THEN EXIT(DoKey);
  2296.                     SetPort(MainWindow);
  2297.                 END;
  2298.                 
  2299.                 IF WSCut(WS) THEN ReDisplay;
  2300.                 
  2301.                 IF (BitAnd(LoWord(EV.Message),255) <> 8)  { If not a backspace }
  2302.                     OR (CharByte(Ptr(@EV.Message),0) <> 0) { Or 2 byte char}
  2303.                 THEN WSKey(WS,EV);
  2304.              END
  2305.              ELSE WSKey(WS,EV);
  2306.              
  2307.              IF NOT PrevFail
  2308.              THEN CurWS.Undo:= BitAnd(LoWord(EV.Message),255) { Save the key as UNDO }
  2309.              ELSE CurWS.Undo:= 0;
  2310.              
  2311.              IF NOT AnArrowKey THEN SetChanges(TRUE);
  2312.              ForceScroll;
  2313.          END;
  2314.      END;
  2315.  END;
  2316.  
  2317.  
  2318.  PROCEDURE DoUpdate;
  2319.  VAR WhatWindow:WindowPtr;
  2320.      R:Rect;
  2321.      
  2322.  BEGIN
  2323.      WhatWindow:= WindowPtr(EV.Message);
  2324.      GetMyWS(WhatWindow);
  2325.  
  2326.      BeginUpdate(WhatWindow);
  2327.      SetPort(WhatWindow);
  2328.      EraseRect(WhatWindow^.PortRect);
  2329.      IF MainWindow <> NIL
  2330.      THEN
  2331.      BEGIN
  2332.         WSDisplay(WS,0,FALSE,TRUE);
  2333.         DrawGrowIcon(MainWindow);
  2334.         DrawControls(MainWindow);
  2335.         LastNumChars:= -1;
  2336.         ShowNumChars;
  2337.      END
  2338.      ELSE
  2339.      IF WhatWindow = ClipWindow
  2340.      THEN
  2341.      BEGIN
  2342.         GetXScrap;                            { Get possible external scrap }
  2343.         IF ScrapWS <> NIL
  2344.         THEN
  2345.         BEGIN
  2346.  { Display the scrap }
  2347.            R:= ClipWindow^.PortRect;        { Start with whole screen }
  2348.            InsetRect(R,4,2);                { Inset a wee bit }
  2349.            ScrapWS^^.tBounds.Top:= R.Top;    { Force bounds to wrap properly }
  2350.            ScrapWS^^.tBounds.Bottom:= R.Bottom;
  2351.            ScrapWS^^.tBounds.Left:= R.Left;
  2352.            ScrapWS^^.tBounds.Right:= R.Right;
  2353.            ScrapWS^^.tRect:= R;                { View is the same }
  2354.            WSDisplay(ScrapWS,0,TRUE,FALSE);
  2355.         END;
  2356.      END;
  2357.  
  2358.      EndUpdate(WhatWindow);
  2359.  END;
  2360.  
  2361.  
  2362.  
  2363.  PROCEDURE MyAction (WhatCTL:ControlHandle; Part:Integer);
  2364.  VAR H,V:LongInt;
  2365.  
  2366.  BEGIN
  2367.     H:= 0;
  2368.     V:= 0;
  2369.  
  2370.     IF WhatCTL = CurWS.vCTL  { If vertical scroll }
  2371.     THEN
  2372.     BEGIN
  2373.        Case Part OF
  2374.           inUpButton:     { Scroll UP }    V:= 16;
  2375.                       
  2376.           inDownButton: { Scroll down } V:= -16;
  2377.  
  2378.           inPageUp:     { Page up }        V:= WS^^.tRect.Bottom-WS^^.tRect.Top;
  2379.                     
  2380.           inPageDown:     { Page down }    V:= WS^^.tRect.Top-WS^^.tRect.Bottom;
  2381.                       
  2382.        END; { of case }
  2383.     END
  2384.     ELSE
  2385.     BEGIN
  2386.       { Horizontal scroll }
  2387.  
  2388.        Case Part OF
  2389.           inUpButton:     { Scroll UP }    H:= 16;
  2390.                       
  2391.           inDownButton: { Scroll down } H:= -16;
  2392.                      
  2393.           inPageUp:     { Page up }        H:= WS^^.tRect.Right-WS^^.tRect.Left;
  2394.                     
  2395.           inPageDown:     { Page down }    H:= WS^^.tRect.Left-WS^^.tRect.Right;
  2396.  
  2397.        END; { of case }
  2398.     END;
  2399.     
  2400.     MasterScroll(H,V);
  2401.  END;
  2402.  
  2403.  
  2404.  FUNCTION ScrollWindow:Boolean;
  2405.  VAR P:Point;
  2406.        WhatCTL:ControlHandle;
  2407.       Part,FinalPart,FirstValue:Integer;
  2408.       H,V,Work,Zero:LongInt;
  2409.  BEGIN
  2410.     P:= EV.Where;                { Global mouse }
  2411.     GlobalToLocal(P);
  2412.     Part:= FindControl(P,MainWindow,WhatCTL);
  2413.     IF Part = 0 THEN ScrollWindow:= FALSE
  2414.     ELSE
  2415.     BEGIN
  2416.        ScrollWindow:= TRUE;
  2417.        SetMouse(0);
  2418.        
  2419.        FirstValue:= GetCTLValue(WhatCTL);
  2420.  
  2421.        IF Part = inThumb
  2422.        THEN FinalPart:= TrackControl(WhatCTL,P,NIL)
  2423.        ELSE FinalPart:= TrackControl(WhatCTL,P,@MyAction);
  2424.        
  2425.        IF FinalPart = inThumb
  2426.        THEN
  2427.        BEGIN
  2428.           Zero:= 0;
  2429.           Part:= GetCTLValue(WhatCTL);
  2430.           IF Part > FirstValue  { If thumb = DOWN }
  2431.           THEN
  2432.           BEGIN
  2433.              Work:= Part-FirstValue;
  2434.              Work:= Work*8;
  2435.              Work:= Zero-Work;        { Makes it negative }
  2436.           END
  2437.           ELSE
  2438.           BEGIN
  2439.              Work:= FirstValue-Part;
  2440.              Work:= Work*8;
  2441.           END;
  2442.           
  2443.           H:= 0;
  2444.           V:= 0;
  2445.           IF WhatCTL = CurWS.vCTL
  2446.           THEN V:= Work ELSE H:= Work;
  2447.           MasterScroll(H,V);
  2448.        END;
  2449.     END;
  2450.  END;
  2451.  
  2452.  
  2453.  { THE FOLLOWING IS A DEMO OF AUTOMATICALLY SCROLLING WITH WS-0 }
  2454.  PROCEDURE MyIdleProc (WS:WSHandle; NewMouse:Point);
  2455.  VAR H,V:LongInt;
  2456.  
  2457.  { Note that outside routines will work since global "WS" has been set prior
  2458.    to mouse dragging began }
  2459.  
  2460.  BEGIN
  2461.     H:= 0;                    { Assume no H-SCROLL }
  2462.     V:= 0;                    { Assume no V-SCROLL }
  2463.     
  2464.     IF NewMouse.V < WS^^.tRect.Top  { If mouse is ABOVE view }
  2465.     THEN V:= 16                { Scroll up a bit }
  2466.     ELSE
  2467.     IF NewMouse.V > WS^^.tRect.Bottom { If mouse below view }
  2468.     THEN V:= -16;            { Scroll down a bit }
  2469.  
  2470.     IF NewMouse.H < WS^^.tRect.Left  { If mouse is left of view }
  2471.     THEN H:= 16                { Scroll forward a bit }
  2472.     ELSE
  2473.     IF NewMouse.H > WS^^.tRect.Right { If mouse right of view }
  2474.     THEN H:= -16;            { Scroll back a bit }
  2475.  
  2476.     IF (H <> 0) OR (V <> 0)   { If I have a scrolling situation }
  2477.     THEN MasterScroll(H,V);
  2478.  
  2479.  END;
  2480.  
  2481.  
  2482.  PROCEDURE DoClick;
  2483.  VAR WhatWindow: WindowPtr;       { Window in questions }
  2484.      Contact,FW:Integer;
  2485.      forMenus,forGrow:LongInt;
  2486.      R:Rect;
  2487.      Dummy:Boolean;
  2488.      P:Point;
  2489.  
  2490.  BEGIN
  2491.     FW:= FindWindow (EV.Where,WhatWindow);
  2492.     GetMyWS(WhatWindow);
  2493.  
  2494.     CASE FW OF
  2495.  
  2496.        inMenuBar:
  2497.                BEGIN
  2498.               MenuEnable;
  2499.               MarkMenus;
  2500.               SetMouse(0);
  2501.               forMenus:= MenuSelect(EV.Where);
  2502.               DoMenus(forMenus);
  2503.             END;
  2504.  
  2505.        inSysWindow:
  2506.             SystemClick(EV,WhatWindow);
  2507.  
  2508.        inContent:
  2509.             IF MainWindow <> NIL THEN
  2510.             BEGIN
  2511.                IF MainWindow <> FrontWindow
  2512.                THEN SelectWindow(MainWindow)
  2513.                ELSE
  2514.                BEGIN
  2515.                   SetPort(MainWindow);
  2516.                   P:= EV.Where;
  2517.                   GlobalToLocal(P);
  2518.                   IF (NOT ScrollWindow)
  2519.                              AND
  2520.                       (PtInRect(P,WS^^.tRect))
  2521.                   THEN
  2522.                   BEGIN
  2523.                       WSClick(WS,EV,@MyIdleProc);               
  2524.                       WSGetSelect(WS,CurWS.UnSel3,CurWS.UnSel3);  { For key-Undo }
  2525.                       SetMyWS(MainWindow);
  2526.                   END;
  2527.                END;
  2528.             END
  2529.             ELSE
  2530.             IF WhatWindow = ClipWindow
  2531.             THEN SelectWindow(ClipWindow);
  2532.  
  2533.        inDrag:
  2534.                BEGIN
  2535.                SetRect(R,0,20,768,400);
  2536.                DragWindow (WhatWindow,EV.Where,R);
  2537.             END;
  2538.  
  2539.        inGrow:
  2540.            BEGIN
  2541.               IF MainWindow <> NIL
  2542.               THEN
  2543.               BEGIN
  2544.                  SetRect(R,0,0,4096,4096);
  2545.                  forGrow:= GrowWindow(MainWindow,EV.Where,R);
  2546.                  IF forGrow <> 0
  2547.                  THEN
  2548.                  BEGIN
  2549.                     KillControls(MainWindow);
  2550.                     SizeWindow(MainWindow,LoWord(forGrow),HiWord(forGrow),TRUE);
  2551.                     SetPort(MainWindow);
  2552.                     R:= MainWindow^.PortRect;
  2553.                     ClipRect(R);
  2554.                     InvalRect(R);
  2555.  
  2556.                     MakeNewControls(MainWindow);
  2557.                     
  2558.                     R:= MainWindow^.PortRect;
  2559.                     R.Right:= CurWS.vCTL^^.contrlRect.Left;
  2560.                     R.Bottom:= CurWS.hCTL^^.contrlRect.Top;
  2561.                     WS^^.tRect:= R;
  2562.                     SetMyWS(MainWindow);
  2563.                     ForceUpdate;
  2564.                     GetMyWS(FrontWindow);
  2565.                     SetMaxScroll;
  2566.                     ShowControl(CurWS.vCTL);
  2567.                     ShowControl(CurWS.hCTL);
  2568.                     LastNumChars:= -1;
  2569.                     ShowNumChars;
  2570.                  END;
  2571.               END;
  2572.            END;
  2573.            
  2574.        inGoAway:
  2575.            BEGIN
  2576.               IF TrackGoAway(WhatWindow,EV.Where)
  2577.               THEN
  2578.               BEGIN
  2579.                  IF WhatWindow = MainWindow THEN Dummy:= CloseMain
  2580.                  ELSE
  2581.                  IF WhatWindow = ClipWindow
  2582.                  THEN
  2583.                  BEGIN
  2584.                     DisposeWindow(ClipWindow);
  2585.                     ClipWindow:= NIL;
  2586.                  END;
  2587.               END;
  2588.            END;
  2589.  
  2590.  
  2591.     END;  { of FindWindow }
  2592.  
  2593.  END;
  2594.  
  2595.  
  2596.  
  2597.  PROCEDURE DoActivate;
  2598.  BEGIN
  2599.     GetMyWS(WindowPtr(EV.Message));
  2600.  
  2601.     IF MainWindow <> NIL
  2602.     THEN
  2603.     BEGIN
  2604.        SetPort(MainWindow);
  2605.        IF BitAnd(EV.Modifiers,1) = 1
  2606.        THEN WSActivate(WS)
  2607.        ELSE WSDeactivate(WS);
  2608.        DrawGrowIcon(MainWindow);
  2609.        DrawControls(MainWindow);    { Assure controls come out right }
  2610.        LastNumChars:= -1;
  2611.        ShowNumChars;
  2612.     END;
  2613.  END;
  2614.  
  2615.  
  2616.  PROCEDURE ForceUpdate;   { Forces update & activate events }
  2617.  VAR Cont:Boolean;
  2618.  
  2619.  BEGIN
  2620.     Cont:= TRUE;
  2621.     REPEAT
  2622.         IF GetNextEvent(EveryEvent,EV)
  2623.         THEN
  2624.         BEGIN
  2625.            Case EV.What OF
  2626.               updateEvt: DoUpdate;
  2627.               activateEvt: DoActivate;
  2628.            END;
  2629.            SystemTask;
  2630.            IF EV.What = 0 THEN Cont:= FALSE;
  2631.         END
  2632.         ELSE Cont:= FALSE;
  2633.     UNTIL NOT Cont;
  2634.     
  2635.  END;
  2636.   
  2637.  
  2638.  FUNCTION MemErrProc (cNeeded:LongInt):Boolean;
  2639.  VAR Result:Integer;
  2640.      TakenFree:LongInt;
  2641.  BEGIN
  2642.     MemErrProc:= FALSE;                    { Don't even try it... }
  2643.     IF cNeeded < 0  { If this is NO RETURN ERROR }
  2644.     THEN
  2645.     BEGIN
  2646.        SetMouse(0);
  2647.        io:= CautionAlert(StupidTester,NIL);
  2648.     END
  2649.     ELSE OpFailed:= TRUE;
  2650.  END;
  2651.  
  2652.  
  2653. { START }
  2654. BEGIN
  2655.      InitGraf(@ThePort);
  2656.      InitFonts;
  2657.      InitWindows;
  2658.      InitMenus;
  2659.      InitDialogs(NIL);
  2660.      TEInit;
  2661.  
  2662.      PHDL:= THPrint(NewHandle(120));
  2663.      PrOpen;
  2664.      PrintDefault(PHDL);    { Set default print record }
  2665.  
  2666.      AppleChar:= ' ';
  2667.      AppleChar[1]:= CHR(20);
  2668.  
  2669.      Menu0:= NewMenu(1,Applechar);      { Make a DA menu }
  2670.      AppendMenu(Menu0,'About This Demo');
  2671.      AppendMenu(Menu0,'(-');
  2672.  
  2673.      AddResMenu(MENU0,'DRVR');
  2674.  
  2675.      Menu3:= NewMenu(300,'Font');       { Get all fonts }
  2676.      AddResMenu(Menu3,'FONT');
  2677.  
  2678.   { Get the rest of the menus: }
  2679.  
  2680.      MENU1:= GetMenu(100);
  2681.      MENU2:= GetMenu(200);
  2682.      MENU4:= GetMenu(400);
  2683.      MENU5:= GetMenu(500);
  2684.      MENU6:= GetMenu(600);
  2685.      MENU7:= GetMenu(700);
  2686.  
  2687.      InsertMenu(MENU0,0);
  2688.      InsertMenu(MENU1,0);
  2689.      InsertMenu(MENU2,0);
  2690.      InsertMenu(MENU3,0);
  2691.      InsertMenu(MENU4,0);
  2692.      InsertMenu(MENU5,0);
  2693.      InsertMenu(MENU6,0);
  2694.      InsertMenu(MENU7,0);
  2695.  
  2696.      DrawMenuBar;
  2697.      
  2698.      ClipWindow:= NIL;            { Clipboard not open }
  2699.      ScrapWS:= NIL;                { Scrap not open }
  2700.      UndoWS:= NIL;                { Undo doesn't exist }
  2701.      FontScrap:= NIL;            { Font Scrap doesn't exist either }
  2702.  
  2703.      WSStartup(128,@MemErrProc);
  2704.  
  2705. { Now obtain any external scrap }
  2706.  
  2707.      XScrap:= InfoScrap;
  2708.      MyScrapNum:= XScrap^.scrapCount-1;        { So I think there's scrap }
  2709.      GetXScrap;                                { Return it. }
  2710.      MyOwnScrap:= FALSE;
  2711.  
  2712.      MainWindow:= NIL;
  2713.      LastNumChars:= -1;
  2714.      ShowCtr:= 0;
  2715.      OpFailed:= FALSE;
  2716.      OpenSelect:= 1;
  2717.      DefFlags:= 0;
  2718.      
  2719.      CountAppFiles(AppMsg,nFiles);
  2720.  
  2721.      IF nFiles > 0 THEN
  2722.      BEGIN
  2723.         GetAppFiles(1,AppData);
  2724.         Quit:= OpenFile(AppData.fName,AppData.vRefNum);
  2725.         ForceUpdate;
  2726.      END
  2727.      ELSE
  2728.      BEGIN
  2729.          OpenMain(NIL,NIL);
  2730.          ForceUpdate;
  2731.          GetMyWS(FrontWindow);
  2732.          SetMaxScroll;
  2733.          ShowControl(CurWS.vCTL);
  2734.          ShowControl(CurWS.hCTL);
  2735.      END;
  2736.  
  2737.      InitCursor;
  2738.      CurCursor:= 0;
  2739.      QUIT:= FALSE;
  2740.      io:= Alert(AboutAlert,NIL);
  2741.      
  2742.      REPEAT
  2743.         IF OpFailed  { If recent operation failed }
  2744.         THEN
  2745.         BEGIN
  2746.            SetMouse(0);
  2747.            io:= CautionAlert(MemFailed,NIL);
  2748.            OpFailed:= FALSE;
  2749.         END;
  2750.         
  2751.         SystemTask;
  2752.  
  2753.         IF GetNextEvent(EveryEvent,EV) THEN
  2754.         BEGIN
  2755.  
  2756.            CASE EV.What OF
  2757.  
  2758.               mouseDown: DoClick;
  2759.  
  2760.               keyDown: REPEAT
  2761.                          DoKey;
  2762.                        UNTIL NOT GetNextEvent(KeyDownMask+AutoKeyMask,EV);
  2763.                        
  2764.  
  2765.               autoKey: REPEAT
  2766.                          DoKey;
  2767.                        UNTIL NOT GetNextEvent(KeyDownMask+AutoKeyMask,EV);
  2768.  
  2769.               updateEvt: DoUpdate;
  2770.  
  2771.               activateEvt: DoActivate;
  2772.  
  2773.            END; { of possible Events }
  2774.  
  2775.         END
  2776.         ELSE
  2777.         BEGIN
  2778.             GetMyWS(FrontWindow);
  2779.             IF MainWindow <> NIL THEN
  2780.             BEGIN
  2781.                SetPort(MainWindow);
  2782.                WSIdle(WS);
  2783.                GetMouse(LocalMouse);
  2784.                IF PtInRect(LocalMouse,WS^^.tRect)
  2785.                THEN SetMouse(iBeamCursor)
  2786.                ELSE SetMouse(0);
  2787.                ShowCtr:= ShowCtr-1;
  2788.                IF ShowCtr < 0 THEN
  2789.                BEGIN
  2790.                   ShowNumChars;
  2791.                   ShowCtr:= 32;
  2792.                END;
  2793.             END;
  2794.         END;
  2795.      UNTIL QUIT;
  2796.  
  2797.      ExitToShell;
  2798. END.
  2799.  
  2800.